blob: b76e2c49e5ed4e33f2e2a0a2781aa8b41fe874f9 [file] [log] [blame]
zonr6315f762010-10-05 15:35:14 +08001#include "slang_rs_backend.h"
2
3#include <vector>
4#include <string>
Shih-wei Liao462aefd2010-06-04 15:32:04 -07005
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07006#include "llvm/Metadata.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07007#include "llvm/Constant.h"
8#include "llvm/Constants.h"
9#include "llvm/Module.h"
10#include "llvm/Function.h"
11#include "llvm/DerivedTypes.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070012
Zonr Chang592a9542010-10-07 20:03:58 +080013#include "llvm/System/Path.h"
14
zonr6315f762010-10-05 15:35:14 +080015#include "llvm/Support/IRBuilder.h"
16
17#include "llvm/ADT/Twine.h"
18#include "llvm/ADT/StringExtras.h"
19
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070020#include "clang/AST/DeclGroup.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070021
Zonr Chang592a9542010-10-07 20:03:58 +080022#include "slang_rs.h"
zonr6315f762010-10-05 15:35:14 +080023#include "slang_rs_context.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080024#include "slang_rs_metadata.h"
zonr6315f762010-10-05 15:35:14 +080025#include "slang_rs_export_var.h"
26#include "slang_rs_export_func.h"
27#include "slang_rs_export_type.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070028
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070029using namespace slang;
30
31RSBackend::RSBackend(RSContext *Context,
32 clang::Diagnostic &Diags,
33 const clang::CodeGenOptions &CodeGenOpts,
34 const clang::TargetOptions &TargetOpts,
35 const PragmaList &Pragmas,
36 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080037 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070038 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080039 bool AllowRSPrefix)
40 : Backend(Diags,
41 CodeGenOpts,
42 TargetOpts,
43 Pragmas,
44 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080045 OT),
zonr6315f762010-10-05 15:35:14 +080046 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080047 mSourceMgr(SourceMgr),
48 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080049 mExportVarMetadata(NULL),
50 mExportFuncMetadata(NULL),
51 mExportTypeMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070052 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070053}
54
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070055void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080056 // Disallow user-defined functions with prefix "rs"
57 if (!mAllowRSPrefix) {
Zonr Chang592a9542010-10-07 20:03:58 +080058 // Iterate all function declarations in the program.
59 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
60 I != E; I++) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080061 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
Zonr Chang592a9542010-10-07 20:03:58 +080062 if (FD == NULL)
63 continue;
64 if (FD->getName().startswith("rs")) { // Check prefix
65 clang::FullSourceLoc FSL(FD->getLocStart(), mSourceMgr);
66 clang::PresumedLoc PLoc = mSourceMgr.getPresumedLoc(FSL);
67 llvm::sys::Path HeaderFilename(PLoc.getFilename());
68
69 // Skip if that function declared in the RS default header.
70 if (SlangRS::IsRSHeaderFile(HeaderFilename.getLast().data()))
71 continue;
72 mDiags.Report(FSL, mDiags.getCustomDiagID(clang::Diagnostic::Error,
73 "invalid function name prefix, \"rs\" is reserved: '%0'"))
74 << FD->getName();
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080075 }
76 }
77 }
78
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070079 Backend::HandleTopLevelDecl(D);
80 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070081}
82
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070083void RSBackend::HandleTranslationUnitEx(clang::ASTContext &Ctx) {
84 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change"
85 " during LLVM IR generation");
86 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070087
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070088 // Dump export variable info
89 if (mContext->hasExportVar()) {
90 if (mExportVarMetadata == NULL)
Zonr Chang7f2f3852010-10-07 19:12:23 +080091 mExportVarMetadata = mpModule->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070092
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070093 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070094
zonr6315f762010-10-05 15:35:14 +080095 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
96 E = mContext->export_vars_end();
97 I != E;
98 I++) {
99 const RSExportVar *EV = *I;
100 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700101
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102 // Variable name
103 ExportVarInfo.push_back(
104 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700105
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700106 // Type name
107 if (ET->getClass() == RSExportType::ExportClassPrimitive)
108 ExportVarInfo.push_back(
109 llvm::MDString::get(
110 mLLVMContext, llvm::utostr_32(
zonr6315f762010-10-05 15:35:14 +0800111 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700112 else if (ET->getClass() == RSExportType::ExportClassPointer)
113 ExportVarInfo.push_back(
114 llvm::MDString::get(
115 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
zonr6315f762010-10-05 15:35:14 +0800116 ->getPointeeType()->getName()).c_str()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700117 else
118 ExportVarInfo.push_back(
119 llvm::MDString::get(mLLVMContext,
120 EV->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700121
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700122 mExportVarMetadata->addOperand(
123 llvm::MDNode::get(mLLVMContext,
124 ExportVarInfo.data(),
125 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700126
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700127 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700128 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700129 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700130
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700131 // Dump export function info
132 if (mContext->hasExportFunc()) {
133 if (mExportFuncMetadata == NULL)
134 mExportFuncMetadata =
Zonr Chang7f2f3852010-10-07 19:12:23 +0800135 mpModule->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700136
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700137 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700138
zonr6315f762010-10-05 15:35:14 +0800139 for (RSContext::const_export_func_iterator
140 I = mContext->export_funcs_begin(),
141 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 I != E;
143 I++) {
zonr6315f762010-10-05 15:35:14 +0800144 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700145
146 // Function name
zonr6315f762010-10-05 15:35:14 +0800147 if (!EF->hasParam()) {
148 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
149 EF->getName().c_str()));
150 } else {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700151 llvm::Function *F = mpModule->getFunction(EF->getName());
152 llvm::Function *HelperFunction;
153 const std::string HelperFunctionName(".helper_" + EF->getName());
154
155 assert(F && "Function marked as exported disappeared in Bitcode");
156
157 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700158 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800159 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700160
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800161 if (!F->getArgumentList().empty()) {
162 std::vector<const llvm::Type*> HelperFunctionParameterTys;
163 for (llvm::Function::arg_iterator AI = F->arg_begin(),
164 AE = F->arg_end(); AI != AE; AI++)
165 HelperFunctionParameterTys.push_back(AI->getType());
166
167 HelperFunctionParameterTy =
168 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
169 }
170
171 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
172 fprintf(stderr, "Failed to export function %s: parameter type "
173 "mismatch during creation of helper function.\n",
174 EF->getName().c_str());
175
176 const RSExportRecordType *Expected = EF->getParamPacketType();
177 if (Expected) {
178 fprintf(stderr, "Expected:\n");
179 Expected->getLLVMType()->dump();
180 }
181 if (HelperFunctionParameterTy) {
182 fprintf(stderr, "Got:\n");
183 HelperFunctionParameterTy->dump();
184 }
185 }
186
187 std::vector<const llvm::Type*> Params;
188 if (HelperFunctionParameterTy) {
189 llvm::PointerType *HelperFunctionParameterTyP =
190 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
191 Params.push_back(HelperFunctionParameterTyP);
192 }
193
194 llvm::FunctionType * HelperFunctionType =
195 llvm::FunctionType::get(F->getReturnType(),
196 Params,
197 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700198
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700199 HelperFunction =
200 llvm::Function::Create(HelperFunctionType,
201 llvm::GlobalValue::ExternalLinkage,
202 HelperFunctionName,
203 mpModule);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700204
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700205 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
206 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700207
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700208 // Create helper function body
209 {
210 llvm::Argument *HelperFunctionParameter =
211 &(*HelperFunction->arg_begin());
212 llvm::BasicBlock *BB =
213 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
214 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
215 llvm::SmallVector<llvm::Value*, 6> Params;
216 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700217
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700218 Idx[0] =
219 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700220
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700221 // getelementptr and load instruction for all elements in
222 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800223 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700224 // getelementptr
225 Idx[1] =
226 llvm::ConstantInt::get(
227 llvm::Type::getInt32Ty(mLLVMContext), i);
228 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
229 Idx,
230 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700231
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700232 // load
233 llvm::Value *V = IB->CreateLoad(Ptr);
234 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700235 }
236
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700237 // Call and pass the all elements as paramter to F
238 llvm::CallInst *CI = IB->CreateCall(F,
239 Params.data(),
240 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700241
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700242 CI->setCallingConv(F->getCallingConv());
243
244 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
245 IB->CreateRetVoid();
246 else
247 IB->CreateRet(CI);
248
249 delete IB;
250 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700251 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700252
253 ExportFuncInfo.push_back(
254 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
255 }
256
257 mExportFuncMetadata->addOperand(
258 llvm::MDNode::get(mLLVMContext,
259 ExportFuncInfo.data(),
260 ExportFuncInfo.size()));
261
262 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700263 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700265
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700266 // Dump export type info
267 if (mContext->hasExportType()) {
268 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700269
zonr6315f762010-10-05 15:35:14 +0800270 for (RSContext::const_export_type_iterator
271 I = mContext->export_types_begin(),
272 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700273 I != E;
274 I++) {
275 // First, dump type name list to export
276 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700277
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700278 ExportTypeInfo.clear();
279 // Type name
280 ExportTypeInfo.push_back(
281 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700282
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700283 if (ET->getClass() == RSExportType::ExportClassRecord) {
284 const RSExportRecordType *ERT =
285 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700286
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700287 if (mExportTypeMetadata == NULL)
288 mExportTypeMetadata =
Zonr Chang7f2f3852010-10-07 19:12:23 +0800289 mpModule->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700291 mExportTypeMetadata->addOperand(
292 llvm::MDNode::get(mLLVMContext,
293 ExportTypeInfo.data(),
294 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700295
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700296 // Now, export struct field information to %[struct name]
297 std::string StructInfoMetadataName("%");
298 StructInfoMetadataName.append(ET->getName());
299 llvm::NamedMDNode *StructInfoMetadata =
300 mpModule->getOrInsertNamedMetadata(StructInfoMetadataName);
301 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700302
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700303 assert(StructInfoMetadata->getNumOperands() == 0 &&
304 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800305 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
306 FE = ERT->fields_end();
307 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700308 FI++) {
309 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700310
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700311 // 1. field name
312 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
313 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700314
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700315 // 2. field type name
316 FieldInfo.push_back(
317 llvm::MDString::get(mLLVMContext,
318 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700319
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 // 3. field kind
321 switch (F->getType()->getClass()) {
322 case RSExportType::ExportClassPrimitive:
323 case RSExportType::ExportClassVector: {
324 const RSExportPrimitiveType *EPT =
325 static_cast<const RSExportPrimitiveType*>(F->getType());
326 FieldInfo.push_back(
327 llvm::MDString::get(mLLVMContext,
328 llvm::itostr(EPT->getKind())));
329 break;
330 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700331
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700332 default: {
333 FieldInfo.push_back(
334 llvm::MDString::get(mLLVMContext,
335 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800336 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700337 break;
338 }
339 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700340
zonr6315f762010-10-05 15:35:14 +0800341 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
342 FieldInfo.data(),
343 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700344
345 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700346 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700347 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700348 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700349 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700351 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700352}
353
354RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700355 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700356}