blob: e6d443776e568c6655180d3be8e5cf6daf14423b [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
zonr6315f762010-10-05 15:35:14 +080013#include "llvm/Support/IRBuilder.h"
14
15#include "llvm/ADT/Twine.h"
16#include "llvm/ADT/StringExtras.h"
17
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070018#include "clang/AST/DeclGroup.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070019
zonr6315f762010-10-05 15:35:14 +080020#include "slang_rs_context.h"
21#include "slang_rs_export_var.h"
22#include "slang_rs_export_func.h"
23#include "slang_rs_export_type.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070024
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070025using namespace slang;
26
27RSBackend::RSBackend(RSContext *Context,
28 clang::Diagnostic &Diags,
29 const clang::CodeGenOptions &CodeGenOpts,
30 const clang::TargetOptions &TargetOpts,
31 const PragmaList &Pragmas,
32 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080033 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070034 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080035 bool AllowRSPrefix)
36 : Backend(Diags,
37 CodeGenOpts,
38 TargetOpts,
39 Pragmas,
40 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080041 OT),
zonr6315f762010-10-05 15:35:14 +080042 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080043 mSourceMgr(SourceMgr),
44 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080045 mExportVarMetadata(NULL),
46 mExportFuncMetadata(NULL),
47 mExportTypeMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070048 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070049}
50
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070051void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080052 // Disallow user-defined functions with prefix "rs"
53 if (!mAllowRSPrefix) {
54 clang::DeclGroupRef::iterator I;
55 for (I = D.begin(); I != D.end(); I++) {
56 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
57 if (!FD || !FD->isThisDeclarationADefinition()) continue;
58 if (FD->getName().startswith("rs")) {
59 mDiags.Report(clang::FullSourceLoc(FD->getLocStart(), mSourceMgr),
60 mDiags.getCustomDiagID(clang::Diagnostic::Error,
61 "invalid function name prefix,"
62 " \"rs\" is reserved: '%0'")
63 )
64 << FD->getNameAsString();
65 }
66 }
67 }
68
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070069 Backend::HandleTopLevelDecl(D);
70 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070071}
72
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070073void RSBackend::HandleTranslationUnitEx(clang::ASTContext &Ctx) {
74 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change"
75 " during LLVM IR generation");
76 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070077
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070078 // Dump export variable info
79 if (mContext->hasExportVar()) {
80 if (mExportVarMetadata == NULL)
81 mExportVarMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_var");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070082
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070083 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070084
zonr6315f762010-10-05 15:35:14 +080085 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
86 E = mContext->export_vars_end();
87 I != E;
88 I++) {
89 const RSExportVar *EV = *I;
90 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070091
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070092 // Variable name
93 ExportVarInfo.push_back(
94 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070095
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070096 // Type name
97 if (ET->getClass() == RSExportType::ExportClassPrimitive)
98 ExportVarInfo.push_back(
99 llvm::MDString::get(
100 mLLVMContext, llvm::utostr_32(
zonr6315f762010-10-05 15:35:14 +0800101 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102 else if (ET->getClass() == RSExportType::ExportClassPointer)
103 ExportVarInfo.push_back(
104 llvm::MDString::get(
105 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
zonr6315f762010-10-05 15:35:14 +0800106 ->getPointeeType()->getName()).c_str()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700107 else
108 ExportVarInfo.push_back(
109 llvm::MDString::get(mLLVMContext,
110 EV->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700111
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700112 mExportVarMetadata->addOperand(
113 llvm::MDNode::get(mLLVMContext,
114 ExportVarInfo.data(),
115 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700116
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700117 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700118 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700119 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700120
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700121 // Dump export function info
122 if (mContext->hasExportFunc()) {
123 if (mExportFuncMetadata == NULL)
124 mExportFuncMetadata =
125 mpModule->getOrInsertNamedMetadata("#rs_export_func");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700126
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700127 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700128
zonr6315f762010-10-05 15:35:14 +0800129 for (RSContext::const_export_func_iterator
130 I = mContext->export_funcs_begin(),
131 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700132 I != E;
133 I++) {
zonr6315f762010-10-05 15:35:14 +0800134 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700135
136 // Function name
zonr6315f762010-10-05 15:35:14 +0800137 if (!EF->hasParam()) {
138 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
139 EF->getName().c_str()));
140 } else {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700141 llvm::Function *F = mpModule->getFunction(EF->getName());
142 llvm::Function *HelperFunction;
143 const std::string HelperFunctionName(".helper_" + EF->getName());
144
145 assert(F && "Function marked as exported disappeared in Bitcode");
146
147 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700148 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800149 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700150
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800151 if (!F->getArgumentList().empty()) {
152 std::vector<const llvm::Type*> HelperFunctionParameterTys;
153 for (llvm::Function::arg_iterator AI = F->arg_begin(),
154 AE = F->arg_end(); AI != AE; AI++)
155 HelperFunctionParameterTys.push_back(AI->getType());
156
157 HelperFunctionParameterTy =
158 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
159 }
160
161 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
162 fprintf(stderr, "Failed to export function %s: parameter type "
163 "mismatch during creation of helper function.\n",
164 EF->getName().c_str());
165
166 const RSExportRecordType *Expected = EF->getParamPacketType();
167 if (Expected) {
168 fprintf(stderr, "Expected:\n");
169 Expected->getLLVMType()->dump();
170 }
171 if (HelperFunctionParameterTy) {
172 fprintf(stderr, "Got:\n");
173 HelperFunctionParameterTy->dump();
174 }
175 }
176
177 std::vector<const llvm::Type*> Params;
178 if (HelperFunctionParameterTy) {
179 llvm::PointerType *HelperFunctionParameterTyP =
180 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
181 Params.push_back(HelperFunctionParameterTyP);
182 }
183
184 llvm::FunctionType * HelperFunctionType =
185 llvm::FunctionType::get(F->getReturnType(),
186 Params,
187 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700188
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700189 HelperFunction =
190 llvm::Function::Create(HelperFunctionType,
191 llvm::GlobalValue::ExternalLinkage,
192 HelperFunctionName,
193 mpModule);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700194
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700195 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
196 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700197
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700198 // Create helper function body
199 {
200 llvm::Argument *HelperFunctionParameter =
201 &(*HelperFunction->arg_begin());
202 llvm::BasicBlock *BB =
203 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
204 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
205 llvm::SmallVector<llvm::Value*, 6> Params;
206 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700207
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700208 Idx[0] =
209 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700210
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700211 // getelementptr and load instruction for all elements in
212 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800213 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700214 // getelementptr
215 Idx[1] =
216 llvm::ConstantInt::get(
217 llvm::Type::getInt32Ty(mLLVMContext), i);
218 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
219 Idx,
220 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700221
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700222 // load
223 llvm::Value *V = IB->CreateLoad(Ptr);
224 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700225 }
226
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700227 // Call and pass the all elements as paramter to F
228 llvm::CallInst *CI = IB->CreateCall(F,
229 Params.data(),
230 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700231
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700232 CI->setCallingConv(F->getCallingConv());
233
234 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
235 IB->CreateRetVoid();
236 else
237 IB->CreateRet(CI);
238
239 delete IB;
240 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700241 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700242
243 ExportFuncInfo.push_back(
244 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
245 }
246
247 mExportFuncMetadata->addOperand(
248 llvm::MDNode::get(mLLVMContext,
249 ExportFuncInfo.data(),
250 ExportFuncInfo.size()));
251
252 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700253 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700254 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700255
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700256 // Dump export type info
257 if (mContext->hasExportType()) {
258 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700259
zonr6315f762010-10-05 15:35:14 +0800260 for (RSContext::const_export_type_iterator
261 I = mContext->export_types_begin(),
262 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700263 I != E;
264 I++) {
265 // First, dump type name list to export
266 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700267
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700268 ExportTypeInfo.clear();
269 // Type name
270 ExportTypeInfo.push_back(
271 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700272
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700273 if (ET->getClass() == RSExportType::ExportClassRecord) {
274 const RSExportRecordType *ERT =
275 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700276
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700277 if (mExportTypeMetadata == NULL)
278 mExportTypeMetadata =
279 mpModule->getOrInsertNamedMetadata("#rs_export_type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700280
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700281 mExportTypeMetadata->addOperand(
282 llvm::MDNode::get(mLLVMContext,
283 ExportTypeInfo.data(),
284 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700285
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700286 // Now, export struct field information to %[struct name]
287 std::string StructInfoMetadataName("%");
288 StructInfoMetadataName.append(ET->getName());
289 llvm::NamedMDNode *StructInfoMetadata =
290 mpModule->getOrInsertNamedMetadata(StructInfoMetadataName);
291 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700292
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 assert(StructInfoMetadata->getNumOperands() == 0 &&
294 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800295 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
296 FE = ERT->fields_end();
297 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700298 FI++) {
299 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700300
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700301 // 1. field name
302 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
303 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700304
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700305 // 2. field type name
306 FieldInfo.push_back(
307 llvm::MDString::get(mLLVMContext,
308 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700309
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700310 // 3. field kind
311 switch (F->getType()->getClass()) {
312 case RSExportType::ExportClassPrimitive:
313 case RSExportType::ExportClassVector: {
314 const RSExportPrimitiveType *EPT =
315 static_cast<const RSExportPrimitiveType*>(F->getType());
316 FieldInfo.push_back(
317 llvm::MDString::get(mLLVMContext,
318 llvm::itostr(EPT->getKind())));
319 break;
320 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700321
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700322 default: {
323 FieldInfo.push_back(
324 llvm::MDString::get(mLLVMContext,
325 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800326 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700327 break;
328 }
329 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700330
zonr6315f762010-10-05 15:35:14 +0800331 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
332 FieldInfo.data(),
333 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700334
335 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700336 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700337 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700338 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700339 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700340
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700341 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700342}
343
344RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700345 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700346}