blob: 09bb6b8ab9812dfe3b846bb04e4112bf19ca5ee4 [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#include "slang_rs_backend.hpp"
2#include "slang_rs_context.hpp"
3#include "slang_rs_export_var.hpp"
4#include "slang_rs_export_func.hpp"
5#include "slang_rs_export_type.hpp"
6
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07007#include "llvm/Metadata.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -07008
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07009#include "llvm/ADT/Twine.h"
10#include "llvm/ADT/StringExtras.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070011
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070012#include "llvm/Support/IRBuilder.h"
13#include "llvm/Constant.h"
14#include "llvm/Constants.h"
15#include "llvm/Module.h"
16#include "llvm/Function.h"
17#include "llvm/DerivedTypes.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070018
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070019#include "clang/AST/DeclGroup.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070020
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070021#include <vector>
22#include <string>
Shih-wei Liao462aefd2010-06-04 15:32:04 -070023
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024using namespace slang;
25
26RSBackend::RSBackend(RSContext *Context,
27 clang::Diagnostic &Diags,
28 const clang::CodeGenOptions &CodeGenOpts,
29 const clang::TargetOptions &TargetOpts,
30 const PragmaList &Pragmas,
31 llvm::raw_ostream *OS,
Kirk Stewart6b226742010-06-11 10:51:12 -070032 SlangCompilerOutputTy OutputType,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070033 clang::SourceManager &SourceMgr,
Kirk Stewart1fd85792010-07-07 09:51:23 -070034 bool AllowRSPrefix) :
Shih-wei Liao462aefd2010-06-04 15:32:04 -070035 Backend(Diags,
36 CodeGenOpts,
37 TargetOpts,
38 Pragmas,
39 OS,
Kirk Stewart6b226742010-06-11 10:51:12 -070040 OutputType,
Kirk Stewart1fd85792010-07-07 09:51:23 -070041 SourceMgr,
42 AllowRSPrefix),
Shih-wei Liaocecd11d2010-09-21 08:07:58 -070043 mContext(Context),
Shih-wei Liao4c9f7422010-08-05 04:30:02 -070044 mExportVarMetadata(NULL),
45 mExportFuncMetadata(NULL),
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070046 mExportTypeMetadata(NULL) {
47 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070048}
49
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070050void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
51 Backend::HandleTopLevelDecl(D);
52 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070053}
54
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070055void RSBackend::HandleTranslationUnitEx(clang::ASTContext &Ctx) {
56 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change"
57 " during LLVM IR generation");
58 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070059
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070060 // Dump export variable info
61 if (mContext->hasExportVar()) {
62 if (mExportVarMetadata == NULL)
63 mExportVarMetadata = mpModule->getOrInsertNamedMetadata("#rs_export_var");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070064
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070065 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070066
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070067 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin();
68 I != mContext->export_vars_end();
69 I++)
70 {
71 const RSExportVar* EV = *I;
72 const RSExportType* ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070073
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070074 // Variable name
75 ExportVarInfo.push_back(
76 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070077
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070078 // Type name
79 if (ET->getClass() == RSExportType::ExportClassPrimitive)
80 ExportVarInfo.push_back(
81 llvm::MDString::get(
82 mLLVMContext, llvm::utostr_32(
83 static_cast<const RSExportPrimitiveType*>(ET)->getType()
84 )));
85 else if (ET->getClass() == RSExportType::ExportClassPointer)
86 ExportVarInfo.push_back(
87 llvm::MDString::get(
88 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
89 ->getPointeeType()->getName()
90 ).c_str()
91 ));
92 else
93 ExportVarInfo.push_back(
94 llvm::MDString::get(mLLVMContext,
95 EV->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070097 mExportVarMetadata->addOperand(
98 llvm::MDNode::get(mLLVMContext,
99 ExportVarInfo.data(),
100 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700101
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700103 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700104 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700105
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700106 // Dump export function info
107 if (mContext->hasExportFunc()) {
108 if (mExportFuncMetadata == NULL)
109 mExportFuncMetadata =
110 mpModule->getOrInsertNamedMetadata("#rs_export_func");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700111
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700112 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700113
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700114 for (RSContext::const_export_func_iterator I=mContext->export_funcs_begin(),
115 E = mContext->export_funcs_end();
116 I != E;
117 I++) {
118 const RSExportFunc* EF = *I;
119
120 // Function name
121 if (!EF->hasParam())
122 ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext,
123 EF->getName().c_str()));
124 else {
125 llvm::Function *F = mpModule->getFunction(EF->getName());
126 llvm::Function *HelperFunction;
127 const std::string HelperFunctionName(".helper_" + EF->getName());
128
129 assert(F && "Function marked as exported disappeared in Bitcode");
130
131 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700132 {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700133 llvm::PointerType *HelperFunctionParameterTypeP =
134 llvm::PointerType::getUnqual(
135 EF->getParamPacketType()->getLLVMType());
136 llvm::FunctionType *HelperFunctionType;
137 std::vector<const llvm::Type*> Params;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700138
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700139 Params.push_back(HelperFunctionParameterTypeP);
140 HelperFunctionType = llvm::FunctionType::get(F->getReturnType(),
141 Params,
142 false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700143
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700144 HelperFunction =
145 llvm::Function::Create(HelperFunctionType,
146 llvm::GlobalValue::ExternalLinkage,
147 HelperFunctionName,
148 mpModule);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700149
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700150 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
151 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700152
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700153 // Create helper function body
154 {
155 llvm::Argument *HelperFunctionParameter =
156 &(*HelperFunction->arg_begin());
157 llvm::BasicBlock *BB =
158 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
159 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
160 llvm::SmallVector<llvm::Value*, 6> Params;
161 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700162
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700163 Idx[0] =
164 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700165
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700166 // getelementptr and load instruction for all elements in
167 // parameter .p
168 for (int i = 0; i < EF->getNumParameters(); i++) {
169 // getelementptr
170 Idx[1] =
171 llvm::ConstantInt::get(
172 llvm::Type::getInt32Ty(mLLVMContext), i);
173 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
174 Idx,
175 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700176
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700177 // load
178 llvm::Value *V = IB->CreateLoad(Ptr);
179 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700180 }
181
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700182 // Call and pass the all elements as paramter to F
183 llvm::CallInst *CI = IB->CreateCall(F,
184 Params.data(),
185 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700186
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187 CI->setCallingConv(F->getCallingConv());
188
189 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
190 IB->CreateRetVoid();
191 else
192 IB->CreateRet(CI);
193
194 delete IB;
195 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700196 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700197
198 ExportFuncInfo.push_back(
199 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
200 }
201
202 mExportFuncMetadata->addOperand(
203 llvm::MDNode::get(mLLVMContext,
204 ExportFuncInfo.data(),
205 ExportFuncInfo.size()));
206
207 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700208 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700209 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700210
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700211 // Dump export type info
212 if (mContext->hasExportType()) {
213 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700214
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700215 for (RSContext::const_export_type_iterator I=mContext->export_types_begin(),
216 E = mContext->export_types_end();
217 I != E;
218 I++) {
219 // First, dump type name list to export
220 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700221
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700222 ExportTypeInfo.clear();
223 // Type name
224 ExportTypeInfo.push_back(
225 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700226
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700227 if (ET->getClass() == RSExportType::ExportClassRecord) {
228 const RSExportRecordType *ERT =
229 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700230
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700231 if (mExportTypeMetadata == NULL)
232 mExportTypeMetadata =
233 mpModule->getOrInsertNamedMetadata("#rs_export_type");
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700234
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235 mExportTypeMetadata->addOperand(
236 llvm::MDNode::get(mLLVMContext,
237 ExportTypeInfo.data(),
238 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700239
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700240 // Now, export struct field information to %[struct name]
241 std::string StructInfoMetadataName("%");
242 StructInfoMetadataName.append(ET->getName());
243 llvm::NamedMDNode *StructInfoMetadata =
244 mpModule->getOrInsertNamedMetadata(StructInfoMetadataName);
245 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700246
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700247 assert(StructInfoMetadata->getNumOperands() == 0 &&
248 "Metadata with same name was created before");
249 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
250 FI != ERT->fields_end();
251 FI++) {
252 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700253
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700254 // 1. field name
255 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
256 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700257
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700258 // 2. field type name
259 FieldInfo.push_back(
260 llvm::MDString::get(mLLVMContext,
261 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700262
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700263 // 3. field kind
264 switch (F->getType()->getClass()) {
265 case RSExportType::ExportClassPrimitive:
266 case RSExportType::ExportClassVector: {
267 const RSExportPrimitiveType *EPT =
268 static_cast<const RSExportPrimitiveType*>(F->getType());
269 FieldInfo.push_back(
270 llvm::MDString::get(mLLVMContext,
271 llvm::itostr(EPT->getKind())));
272 break;
273 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700274
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700275 default: {
276 FieldInfo.push_back(
277 llvm::MDString::get(mLLVMContext,
278 llvm::itostr(
279 RSExportPrimitiveType::DataKindUser
280 )));
281 break;
282 }
283 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700284
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700285 StructInfoMetadata->addOperand( llvm::MDNode::get(mLLVMContext,
286 FieldInfo.data(),
287 FieldInfo.size()));
288
289 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700291 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700292 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700294
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700295 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700296}
297
298RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700299 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700300}