blob: 32131282b18437c561943363531231b2b684a6ee [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"
Zonr Chang7f2f3852010-10-07 19:12:23 +080021#include "slang_rs_metadata.h"
zonr6315f762010-10-05 15:35:14 +080022#include "slang_rs_export_var.h"
23#include "slang_rs_export_func.h"
24#include "slang_rs_export_type.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070025
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070026using namespace slang;
27
28RSBackend::RSBackend(RSContext *Context,
29 clang::Diagnostic &Diags,
30 const clang::CodeGenOptions &CodeGenOpts,
31 const clang::TargetOptions &TargetOpts,
32 const PragmaList &Pragmas,
33 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080034 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070035 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080036 bool AllowRSPrefix)
37 : Backend(Diags,
38 CodeGenOpts,
39 TargetOpts,
40 Pragmas,
41 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080042 OT),
zonr6315f762010-10-05 15:35:14 +080043 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080044 mSourceMgr(SourceMgr),
45 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080046 mExportVarMetadata(NULL),
47 mExportFuncMetadata(NULL),
48 mExportTypeMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070049 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070050}
51
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070052void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080053 // Disallow user-defined functions with prefix "rs"
54 if (!mAllowRSPrefix) {
55 clang::DeclGroupRef::iterator I;
56 for (I = D.begin(); I != D.end(); I++) {
57 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
58 if (!FD || !FD->isThisDeclarationADefinition()) continue;
59 if (FD->getName().startswith("rs")) {
60 mDiags.Report(clang::FullSourceLoc(FD->getLocStart(), mSourceMgr),
61 mDiags.getCustomDiagID(clang::Diagnostic::Error,
62 "invalid function name prefix,"
63 " \"rs\" is reserved: '%0'")
64 )
65 << FD->getNameAsString();
66 }
67 }
68 }
69
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070070 Backend::HandleTopLevelDecl(D);
71 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070072}
73
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070074void RSBackend::HandleTranslationUnitEx(clang::ASTContext &Ctx) {
75 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change"
76 " during LLVM IR generation");
77 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070078
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070079 // Dump export variable info
80 if (mContext->hasExportVar()) {
81 if (mExportVarMetadata == NULL)
Zonr Chang7f2f3852010-10-07 19:12:23 +080082 mExportVarMetadata = mpModule->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070083
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070084 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070085
zonr6315f762010-10-05 15:35:14 +080086 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
87 E = mContext->export_vars_end();
88 I != E;
89 I++) {
90 const RSExportVar *EV = *I;
91 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070092
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070093 // Variable name
94 ExportVarInfo.push_back(
95 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070097 // Type name
98 if (ET->getClass() == RSExportType::ExportClassPrimitive)
99 ExportVarInfo.push_back(
100 llvm::MDString::get(
101 mLLVMContext, llvm::utostr_32(
zonr6315f762010-10-05 15:35:14 +0800102 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700103 else if (ET->getClass() == RSExportType::ExportClassPointer)
104 ExportVarInfo.push_back(
105 llvm::MDString::get(
106 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
zonr6315f762010-10-05 15:35:14 +0800107 ->getPointeeType()->getName()).c_str()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700108 else
109 ExportVarInfo.push_back(
110 llvm::MDString::get(mLLVMContext,
111 EV->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700112
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700113 mExportVarMetadata->addOperand(
114 llvm::MDNode::get(mLLVMContext,
115 ExportVarInfo.data(),
116 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700117
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700118 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700119 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700120 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700121
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700122 // Dump export function info
123 if (mContext->hasExportFunc()) {
124 if (mExportFuncMetadata == NULL)
125 mExportFuncMetadata =
Zonr Chang7f2f3852010-10-07 19:12:23 +0800126 mpModule->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700127
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700128 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700129
zonr6315f762010-10-05 15:35:14 +0800130 for (RSContext::const_export_func_iterator
131 I = mContext->export_funcs_begin(),
132 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700133 I != E;
134 I++) {
zonr6315f762010-10-05 15:35:14 +0800135 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700136
137 // Function name
zonr6315f762010-10-05 15:35:14 +0800138 if (!EF->hasParam()) {
139 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
140 EF->getName().c_str()));
141 } else {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 llvm::Function *F = mpModule->getFunction(EF->getName());
143 llvm::Function *HelperFunction;
144 const std::string HelperFunctionName(".helper_" + EF->getName());
145
146 assert(F && "Function marked as exported disappeared in Bitcode");
147
148 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700149 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800150 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700151
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800152 if (!F->getArgumentList().empty()) {
153 std::vector<const llvm::Type*> HelperFunctionParameterTys;
154 for (llvm::Function::arg_iterator AI = F->arg_begin(),
155 AE = F->arg_end(); AI != AE; AI++)
156 HelperFunctionParameterTys.push_back(AI->getType());
157
158 HelperFunctionParameterTy =
159 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
160 }
161
162 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
163 fprintf(stderr, "Failed to export function %s: parameter type "
164 "mismatch during creation of helper function.\n",
165 EF->getName().c_str());
166
167 const RSExportRecordType *Expected = EF->getParamPacketType();
168 if (Expected) {
169 fprintf(stderr, "Expected:\n");
170 Expected->getLLVMType()->dump();
171 }
172 if (HelperFunctionParameterTy) {
173 fprintf(stderr, "Got:\n");
174 HelperFunctionParameterTy->dump();
175 }
176 }
177
178 std::vector<const llvm::Type*> Params;
179 if (HelperFunctionParameterTy) {
180 llvm::PointerType *HelperFunctionParameterTyP =
181 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
182 Params.push_back(HelperFunctionParameterTyP);
183 }
184
185 llvm::FunctionType * HelperFunctionType =
186 llvm::FunctionType::get(F->getReturnType(),
187 Params,
188 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700189
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700190 HelperFunction =
191 llvm::Function::Create(HelperFunctionType,
192 llvm::GlobalValue::ExternalLinkage,
193 HelperFunctionName,
194 mpModule);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700195
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700196 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
197 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700198
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700199 // Create helper function body
200 {
201 llvm::Argument *HelperFunctionParameter =
202 &(*HelperFunction->arg_begin());
203 llvm::BasicBlock *BB =
204 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
205 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
206 llvm::SmallVector<llvm::Value*, 6> Params;
207 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700208
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700209 Idx[0] =
210 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700211
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700212 // getelementptr and load instruction for all elements in
213 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800214 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700215 // getelementptr
216 Idx[1] =
217 llvm::ConstantInt::get(
218 llvm::Type::getInt32Ty(mLLVMContext), i);
219 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
220 Idx,
221 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700222
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700223 // load
224 llvm::Value *V = IB->CreateLoad(Ptr);
225 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700226 }
227
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700228 // Call and pass the all elements as paramter to F
229 llvm::CallInst *CI = IB->CreateCall(F,
230 Params.data(),
231 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700232
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700233 CI->setCallingConv(F->getCallingConv());
234
235 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
236 IB->CreateRetVoid();
237 else
238 IB->CreateRet(CI);
239
240 delete IB;
241 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700242 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700243
244 ExportFuncInfo.push_back(
245 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
246 }
247
248 mExportFuncMetadata->addOperand(
249 llvm::MDNode::get(mLLVMContext,
250 ExportFuncInfo.data(),
251 ExportFuncInfo.size()));
252
253 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700254 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700255 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700256
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700257 // Dump export type info
258 if (mContext->hasExportType()) {
259 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700260
zonr6315f762010-10-05 15:35:14 +0800261 for (RSContext::const_export_type_iterator
262 I = mContext->export_types_begin(),
263 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 I != E;
265 I++) {
266 // First, dump type name list to export
267 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700268
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700269 ExportTypeInfo.clear();
270 // Type name
271 ExportTypeInfo.push_back(
272 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700273
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 if (ET->getClass() == RSExportType::ExportClassRecord) {
275 const RSExportRecordType *ERT =
276 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700277
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700278 if (mExportTypeMetadata == NULL)
279 mExportTypeMetadata =
Zonr Chang7f2f3852010-10-07 19:12:23 +0800280 mpModule->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700281
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700282 mExportTypeMetadata->addOperand(
283 llvm::MDNode::get(mLLVMContext,
284 ExportTypeInfo.data(),
285 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700286
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700287 // Now, export struct field information to %[struct name]
288 std::string StructInfoMetadataName("%");
289 StructInfoMetadataName.append(ET->getName());
290 llvm::NamedMDNode *StructInfoMetadata =
291 mpModule->getOrInsertNamedMetadata(StructInfoMetadataName);
292 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700293
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700294 assert(StructInfoMetadata->getNumOperands() == 0 &&
295 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800296 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
297 FE = ERT->fields_end();
298 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700299 FI++) {
300 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700301
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700302 // 1. field name
303 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
304 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700305
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700306 // 2. field type name
307 FieldInfo.push_back(
308 llvm::MDString::get(mLLVMContext,
309 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700310
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700311 // 3. field kind
312 switch (F->getType()->getClass()) {
313 case RSExportType::ExportClassPrimitive:
314 case RSExportType::ExportClassVector: {
315 const RSExportPrimitiveType *EPT =
316 static_cast<const RSExportPrimitiveType*>(F->getType());
317 FieldInfo.push_back(
318 llvm::MDString::get(mLLVMContext,
319 llvm::itostr(EPT->getKind())));
320 break;
321 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700322
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700323 default: {
324 FieldInfo.push_back(
325 llvm::MDString::get(mLLVMContext,
326 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800327 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700328 break;
329 }
330 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700331
zonr6315f762010-10-05 15:35:14 +0800332 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
333 FieldInfo.data(),
334 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700335
336 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700337 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700338 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700339 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700340 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700341
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700342 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700343}
344
345RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700346 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700347}