blob: 7f4c4cb896665f6661f3b52bfe346555449eef67 [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
121 if (ET->getClass() == RSExportType::ExportClassPrimitive)
122 ExportVarInfo.push_back(
123 llvm::MDString::get(
124 mLLVMContext, llvm::utostr_32(
zonr6315f762010-10-05 15:35:14 +0800125 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700126 else if (ET->getClass() == RSExportType::ExportClassPointer)
127 ExportVarInfo.push_back(
128 llvm::MDString::get(
129 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
zonr6315f762010-10-05 15:35:14 +0800130 ->getPointeeType()->getName()).c_str()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700131 else
132 ExportVarInfo.push_back(
133 llvm::MDString::get(mLLVMContext,
134 EV->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700135
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700136 mExportVarMetadata->addOperand(
137 llvm::MDNode::get(mLLVMContext,
138 ExportVarInfo.data(),
139 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700140
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700141 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700142 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700143 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700144
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700145 // Dump export function info
146 if (mContext->hasExportFunc()) {
147 if (mExportFuncMetadata == NULL)
148 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800149 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700150
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700151 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700152
zonr6315f762010-10-05 15:35:14 +0800153 for (RSContext::const_export_func_iterator
154 I = mContext->export_funcs_begin(),
155 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700156 I != E;
157 I++) {
zonr6315f762010-10-05 15:35:14 +0800158 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700159
160 // Function name
zonr6315f762010-10-05 15:35:14 +0800161 if (!EF->hasParam()) {
162 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
163 EF->getName().c_str()));
164 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800165 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700166 llvm::Function *HelperFunction;
167 const std::string HelperFunctionName(".helper_" + EF->getName());
168
169 assert(F && "Function marked as exported disappeared in Bitcode");
170
171 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700172 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800173 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700174
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800175 if (!F->getArgumentList().empty()) {
176 std::vector<const llvm::Type*> HelperFunctionParameterTys;
177 for (llvm::Function::arg_iterator AI = F->arg_begin(),
178 AE = F->arg_end(); AI != AE; AI++)
179 HelperFunctionParameterTys.push_back(AI->getType());
180
181 HelperFunctionParameterTy =
182 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
183 }
184
185 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
186 fprintf(stderr, "Failed to export function %s: parameter type "
187 "mismatch during creation of helper function.\n",
188 EF->getName().c_str());
189
190 const RSExportRecordType *Expected = EF->getParamPacketType();
191 if (Expected) {
192 fprintf(stderr, "Expected:\n");
193 Expected->getLLVMType()->dump();
194 }
195 if (HelperFunctionParameterTy) {
196 fprintf(stderr, "Got:\n");
197 HelperFunctionParameterTy->dump();
198 }
199 }
200
201 std::vector<const llvm::Type*> Params;
202 if (HelperFunctionParameterTy) {
203 llvm::PointerType *HelperFunctionParameterTyP =
204 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
205 Params.push_back(HelperFunctionParameterTyP);
206 }
207
208 llvm::FunctionType * HelperFunctionType =
209 llvm::FunctionType::get(F->getReturnType(),
210 Params,
211 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700212
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700213 HelperFunction =
214 llvm::Function::Create(HelperFunctionType,
215 llvm::GlobalValue::ExternalLinkage,
216 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800217 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700218
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700219 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
220 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700221
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700222 // Create helper function body
223 {
224 llvm::Argument *HelperFunctionParameter =
225 &(*HelperFunction->arg_begin());
226 llvm::BasicBlock *BB =
227 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
228 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
229 llvm::SmallVector<llvm::Value*, 6> Params;
230 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700231
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700232 Idx[0] =
233 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700234
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235 // getelementptr and load instruction for all elements in
236 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800237 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700238 // getelementptr
239 Idx[1] =
240 llvm::ConstantInt::get(
241 llvm::Type::getInt32Ty(mLLVMContext), i);
242 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
243 Idx,
244 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700245
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700246 // load
247 llvm::Value *V = IB->CreateLoad(Ptr);
248 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700249 }
250
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700251 // Call and pass the all elements as paramter to F
252 llvm::CallInst *CI = IB->CreateCall(F,
253 Params.data(),
254 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700255
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700256 CI->setCallingConv(F->getCallingConv());
257
258 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
259 IB->CreateRetVoid();
260 else
261 IB->CreateRet(CI);
262
263 delete IB;
264 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700265 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700266
267 ExportFuncInfo.push_back(
268 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
269 }
270
271 mExportFuncMetadata->addOperand(
272 llvm::MDNode::get(mLLVMContext,
273 ExportFuncInfo.data(),
274 ExportFuncInfo.size()));
275
276 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700277 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700278 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700279
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700280 // Dump export type info
281 if (mContext->hasExportType()) {
282 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700283
zonr6315f762010-10-05 15:35:14 +0800284 for (RSContext::const_export_type_iterator
285 I = mContext->export_types_begin(),
286 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700287 I != E;
288 I++) {
289 // First, dump type name list to export
290 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700291
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700292 ExportTypeInfo.clear();
293 // Type name
294 ExportTypeInfo.push_back(
295 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700296
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700297 if (ET->getClass() == RSExportType::ExportClassRecord) {
298 const RSExportRecordType *ERT =
299 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700300
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700301 if (mExportTypeMetadata == NULL)
302 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800303 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700304
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700305 mExportTypeMetadata->addOperand(
306 llvm::MDNode::get(mLLVMContext,
307 ExportTypeInfo.data(),
308 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700309
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700310 // Now, export struct field information to %[struct name]
311 std::string StructInfoMetadataName("%");
312 StructInfoMetadataName.append(ET->getName());
313 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800314 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700315 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700316
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700317 assert(StructInfoMetadata->getNumOperands() == 0 &&
318 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800319 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
320 FE = ERT->fields_end();
321 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700322 FI++) {
323 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700324
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700325 // 1. field name
326 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
327 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700328
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700329 // 2. field type name
330 FieldInfo.push_back(
331 llvm::MDString::get(mLLVMContext,
332 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700333
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700334 // 3. field kind
335 switch (F->getType()->getClass()) {
336 case RSExportType::ExportClassPrimitive:
337 case RSExportType::ExportClassVector: {
338 const RSExportPrimitiveType *EPT =
339 static_cast<const RSExportPrimitiveType*>(F->getType());
340 FieldInfo.push_back(
341 llvm::MDString::get(mLLVMContext,
342 llvm::itostr(EPT->getKind())));
343 break;
344 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700345
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700346 default: {
347 FieldInfo.push_back(
348 llvm::MDString::get(mLLVMContext,
349 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800350 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700351 break;
352 }
353 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700354
zonr6315f762010-10-05 15:35:14 +0800355 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
356 FieldInfo.data(),
357 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700358
359 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700360 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700361 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700362 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700363 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700364
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700365 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700366}
367
368RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700369 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700370}