blob: 9d8684aae658fd0c820fe263513f0ba6b30fb048 [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
Zonr Chang592a9542010-10-07 20:03:58 +080029#include "llvm/System/Path.h"
30
zonr6315f762010-10-05 15:35:14 +080031#include "llvm/Support/IRBuilder.h"
32
33#include "llvm/ADT/Twine.h"
34#include "llvm/ADT/StringExtras.h"
35
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070036#include "clang/AST/DeclGroup.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070037
Zonr Chang592a9542010-10-07 20:03:58 +080038#include "slang_rs.h"
zonr6315f762010-10-05 15:35:14 +080039#include "slang_rs_context.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080040#include "slang_rs_metadata.h"
zonr6315f762010-10-05 15:35:14 +080041#include "slang_rs_export_var.h"
42#include "slang_rs_export_func.h"
43#include "slang_rs_export_type.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070044
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070045using namespace slang;
46
47RSBackend::RSBackend(RSContext *Context,
48 clang::Diagnostic &Diags,
49 const clang::CodeGenOptions &CodeGenOpts,
50 const clang::TargetOptions &TargetOpts,
51 const PragmaList &Pragmas,
52 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080053 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070054 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080055 bool AllowRSPrefix)
56 : Backend(Diags,
57 CodeGenOpts,
58 TargetOpts,
59 Pragmas,
60 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080061 OT),
zonr6315f762010-10-05 15:35:14 +080062 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080063 mSourceMgr(SourceMgr),
64 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080065 mExportVarMetadata(NULL),
66 mExportFuncMetadata(NULL),
67 mExportTypeMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070068 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070069}
70
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070071void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080072 // Disallow user-defined functions with prefix "rs"
73 if (!mAllowRSPrefix) {
Zonr Chang592a9542010-10-07 20:03:58 +080074 // Iterate all function declarations in the program.
75 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
76 I != E; I++) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080077 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
Zonr Chang592a9542010-10-07 20:03:58 +080078 if (FD == NULL)
79 continue;
80 if (FD->getName().startswith("rs")) { // Check prefix
81 clang::FullSourceLoc FSL(FD->getLocStart(), mSourceMgr);
82 clang::PresumedLoc PLoc = mSourceMgr.getPresumedLoc(FSL);
83 llvm::sys::Path HeaderFilename(PLoc.getFilename());
84
85 // Skip if that function declared in the RS default header.
86 if (SlangRS::IsRSHeaderFile(HeaderFilename.getLast().data()))
87 continue;
88 mDiags.Report(FSL, mDiags.getCustomDiagID(clang::Diagnostic::Error,
89 "invalid function name prefix, \"rs\" is reserved: '%0'"))
90 << FD->getName();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080091 }
92 }
93 }
94
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070095 Backend::HandleTopLevelDecl(D);
96 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070097}
98
Zonr Chang68fc02c2010-10-13 19:09:19 +080099void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700100 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700101
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102 // Dump export variable info
103 if (mContext->hasExportVar()) {
104 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800105 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700106
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700107 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700108
zonr6315f762010-10-05 15:35:14 +0800109 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
110 E = mContext->export_vars_end();
111 I != E;
112 I++) {
113 const RSExportVar *EV = *I;
114 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700115
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700116 // Variable name
117 ExportVarInfo.push_back(
118 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700119
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700120 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800121 switch (ET->getClass()) {
122 case RSExportType::ExportClassPrimitive: {
123 ExportVarInfo.push_back(
124 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700125 mLLVMContext, llvm::utostr_32(
Zonr Changa65ec162010-10-17 01:53:05 +0800126 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
127 break;
128 }
129 case RSExportType::ExportClassPointer: {
130 ExportVarInfo.push_back(
131 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700132 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800133 ->getPointeeType()->getName()).c_str()));
134 break;
135 }
136 case RSExportType::ExportClassMatrix: {
137 ExportVarInfo.push_back(
138 llvm::MDString::get(
139 mLLVMContext, llvm::utostr_32(
140 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
141 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
142 break;
143 }
144 case RSExportType::ExportClassVector:
145 case RSExportType::ExportClassConstantArray:
146 case RSExportType::ExportClassRecord: {
147 ExportVarInfo.push_back(
148 llvm::MDString::get(mLLVMContext,
149 EV->getType()->getName().c_str()));
150 break;
151 }
152 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700153
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700154 mExportVarMetadata->addOperand(
155 llvm::MDNode::get(mLLVMContext,
156 ExportVarInfo.data(),
157 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700158
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700159 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700160 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700161 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700162
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700163 // Dump export function info
164 if (mContext->hasExportFunc()) {
165 if (mExportFuncMetadata == NULL)
166 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800167 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700168
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700169 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700170
zonr6315f762010-10-05 15:35:14 +0800171 for (RSContext::const_export_func_iterator
172 I = mContext->export_funcs_begin(),
173 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700174 I != E;
175 I++) {
zonr6315f762010-10-05 15:35:14 +0800176 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700177
178 // Function name
zonr6315f762010-10-05 15:35:14 +0800179 if (!EF->hasParam()) {
180 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
181 EF->getName().c_str()));
182 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800183 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700184 llvm::Function *HelperFunction;
185 const std::string HelperFunctionName(".helper_" + EF->getName());
186
187 assert(F && "Function marked as exported disappeared in Bitcode");
188
189 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700190 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800191 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700192
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800193 if (!F->getArgumentList().empty()) {
194 std::vector<const llvm::Type*> HelperFunctionParameterTys;
195 for (llvm::Function::arg_iterator AI = F->arg_begin(),
196 AE = F->arg_end(); AI != AE; AI++)
197 HelperFunctionParameterTys.push_back(AI->getType());
198
199 HelperFunctionParameterTy =
200 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
201 }
202
203 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
204 fprintf(stderr, "Failed to export function %s: parameter type "
205 "mismatch during creation of helper function.\n",
206 EF->getName().c_str());
207
208 const RSExportRecordType *Expected = EF->getParamPacketType();
209 if (Expected) {
210 fprintf(stderr, "Expected:\n");
211 Expected->getLLVMType()->dump();
212 }
213 if (HelperFunctionParameterTy) {
214 fprintf(stderr, "Got:\n");
215 HelperFunctionParameterTy->dump();
216 }
217 }
218
219 std::vector<const llvm::Type*> Params;
220 if (HelperFunctionParameterTy) {
221 llvm::PointerType *HelperFunctionParameterTyP =
222 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
223 Params.push_back(HelperFunctionParameterTyP);
224 }
225
226 llvm::FunctionType * HelperFunctionType =
227 llvm::FunctionType::get(F->getReturnType(),
228 Params,
229 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700230
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700231 HelperFunction =
232 llvm::Function::Create(HelperFunctionType,
233 llvm::GlobalValue::ExternalLinkage,
234 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800235 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700236
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700237 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
238 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700239
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700240 // Create helper function body
241 {
242 llvm::Argument *HelperFunctionParameter =
243 &(*HelperFunction->arg_begin());
244 llvm::BasicBlock *BB =
245 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
246 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
247 llvm::SmallVector<llvm::Value*, 6> Params;
248 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700249
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700250 Idx[0] =
251 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700252
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700253 // getelementptr and load instruction for all elements in
254 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800255 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700256 // getelementptr
257 Idx[1] =
258 llvm::ConstantInt::get(
259 llvm::Type::getInt32Ty(mLLVMContext), i);
260 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
261 Idx,
262 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700263
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 // load
265 llvm::Value *V = IB->CreateLoad(Ptr);
266 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700267 }
268
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700269 // Call and pass the all elements as paramter to F
270 llvm::CallInst *CI = IB->CreateCall(F,
271 Params.data(),
272 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700273
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 CI->setCallingConv(F->getCallingConv());
275
276 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
277 IB->CreateRetVoid();
278 else
279 IB->CreateRet(CI);
280
281 delete IB;
282 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700283 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700284
285 ExportFuncInfo.push_back(
286 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
287 }
288
289 mExportFuncMetadata->addOperand(
290 llvm::MDNode::get(mLLVMContext,
291 ExportFuncInfo.data(),
292 ExportFuncInfo.size()));
293
294 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700295 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700296 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700297
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700298 // Dump export type info
299 if (mContext->hasExportType()) {
300 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700301
zonr6315f762010-10-05 15:35:14 +0800302 for (RSContext::const_export_type_iterator
303 I = mContext->export_types_begin(),
304 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700305 I != E;
306 I++) {
307 // First, dump type name list to export
308 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700309
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700310 ExportTypeInfo.clear();
311 // Type name
312 ExportTypeInfo.push_back(
313 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700314
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700315 if (ET->getClass() == RSExportType::ExportClassRecord) {
316 const RSExportRecordType *ERT =
317 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700318
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700319 if (mExportTypeMetadata == NULL)
320 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800321 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700322
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700323 mExportTypeMetadata->addOperand(
324 llvm::MDNode::get(mLLVMContext,
325 ExportTypeInfo.data(),
326 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700327
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700328 // Now, export struct field information to %[struct name]
329 std::string StructInfoMetadataName("%");
330 StructInfoMetadataName.append(ET->getName());
331 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800332 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700333 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700334
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700335 assert(StructInfoMetadata->getNumOperands() == 0 &&
336 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800337 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
338 FE = ERT->fields_end();
339 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700340 FI++) {
341 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700342
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700343 // 1. field name
344 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
345 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700346
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700347 // 2. field type name
348 FieldInfo.push_back(
349 llvm::MDString::get(mLLVMContext,
350 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700351
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700352 // 3. field kind
353 switch (F->getType()->getClass()) {
354 case RSExportType::ExportClassPrimitive:
355 case RSExportType::ExportClassVector: {
356 const RSExportPrimitiveType *EPT =
357 static_cast<const RSExportPrimitiveType*>(F->getType());
358 FieldInfo.push_back(
359 llvm::MDString::get(mLLVMContext,
360 llvm::itostr(EPT->getKind())));
361 break;
362 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700363
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700364 default: {
365 FieldInfo.push_back(
366 llvm::MDString::get(mLLVMContext,
367 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800368 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700369 break;
370 }
371 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700372
zonr6315f762010-10-05 15:35:14 +0800373 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
374 FieldInfo.data(),
375 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700376
377 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700378 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700379 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700380 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700381 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700382
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700383 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700384}
385
386RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700387 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700388}