blob: a819d5f9d1b59c21dba86c2fd26d4ee0a7b36c25 [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#include <vector>
2#include <string>
3
4#include "slang_rs_backend.hpp"
5#include "slang_rs_context.hpp"
6#include "slang_rs_export_var.hpp"
7#include "slang_rs_export_func.hpp"
8#include "slang_rs_export_type.hpp"
9
10#include "llvm/Metadata.h" /* for class llvm::NamedMDNode */
11#include "llvm/ADT/Twine.h" /* for class llvm::Twine */
12
13#include "clang/AST/DeclGroup.h" /* for class clang::DeclGroup */
14#include "llvm/ADT/StringExtras.h" /* for function llvm::utostr_32() and llvm::itostr() */
15
16#include "llvm/Support/IRBuilder.h" /* for class llvm::IRBuilder */
17#include "llvm/Constant.h" /* for class llvm::Constant */
18#include "llvm/Constants.h" /* for class llvm::Constant* */
19#include "llvm/Module.h" /* for class llvm::Module */
20#include "llvm/Function.h" /* for class llvm::Function */
21#include "llvm/DerivedTypes.h" /* for class llvm::*Type */
22
23#define MAKE
24
25namespace slang {
26
27RSBackend::RSBackend(RSContext* Context,
28 Diagnostic &Diags,
29 const CodeGenOptions& CodeGenOpts,
30 const TargetOptions& TargetOpts,
31 const PragmaList& Pragmas,
32 llvm::raw_ostream* OS,
Kirk Stewart6b226742010-06-11 10:51:12 -070033 SlangCompilerOutputTy OutputType,
Kirk Stewart1fd85792010-07-07 09:51:23 -070034 SourceManager& SourceMgr,
35 bool AllowRSPrefix) :
Shih-wei Liao462aefd2010-06-04 15:32:04 -070036 mContext(Context),
37 Backend(Diags,
38 CodeGenOpts,
39 TargetOpts,
40 Pragmas,
41 OS,
Kirk Stewart6b226742010-06-11 10:51:12 -070042 OutputType,
Kirk Stewart1fd85792010-07-07 09:51:23 -070043 SourceMgr,
44 AllowRSPrefix),
Shih-wei Liao462aefd2010-06-04 15:32:04 -070045 mExportVarMetadata(NULL)
46{
47 return;
48}
49
50void RSBackend::HandleTopLevelDecl(DeclGroupRef D) {
51 Backend::HandleTopLevelDecl(D);
52 return;
53}
54
55void RSBackend::HandleTranslationUnitEx(ASTContext& Ctx) {
Shih-wei Liao001fb6d2010-06-21 11:17:11 -070056 assert((&Ctx == mContext->getASTContext()) && "Unexpected AST context change during LLVM IR generation");
57 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070058
59 /* Dump export variable info */
60 if(mContext->hasExportVar()) {
61 if(mExportVarMetadata == NULL)
62 mExportVarMetadata = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_var", NULL, 0, mpModule);
63
64 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
65
66 for(RSContext::const_export_var_iterator I = mContext->export_vars_begin();
67 I != mContext->export_vars_end();
68 I++)
69 {
70 const RSExportVar* EV = *I;
71 const RSExportType* ET = EV->getType();
72
73 /* variable name */
74 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, EV->getName().c_str()) );
75
76 /* type name */
77 if(ET->getClass() == RSExportType::ExportClassPrimitive)
78 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::utostr_32(static_cast<const RSExportPrimitiveType*>(ET)->getType())) );
79 else if(ET->getClass() == RSExportType::ExportClassPointer)
80 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)->getPointeeType()->getName()).c_str()) );
81 else
82 ExportVarInfo.push_back( llvm::MDString::get(mLLVMContext, EV->getType()->getName().c_str()) );
83
84 mExportVarMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportVarInfo.data(), ExportVarInfo.size()) );
85
86 ExportVarInfo.clear();
87 }
88 }
89
90 /* Dump export function info */
91 if(mContext->hasExportFunc()) {
92 if(mExportFuncMetadata == NULL)
93 mExportFuncMetadata = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_func", NULL, 0, mpModule);
94
95 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
96
97 for(RSContext::const_export_func_iterator I = mContext->export_funcs_begin();
98 I != mContext->export_funcs_end();
99 I++)
100 {
101 const RSExportFunc* EF = *I;
102
103 /* function name */
104 if(!EF->hasParam())
105 ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, EF->getName().c_str()) );
106 else {
107 llvm::Function* F = mpModule->getFunction(EF->getName());
108 llvm::Function* HelperFunction;
109 const std::string HelperFunctionName = ".helper_" + EF->getName();
110
111 assert(F && "Function marked as exported disappeared in Bitcode");
112
113 /* Create helper function */
114 {
115 llvm::PointerType* HelperFunctionParameterTypeP = llvm::PointerType::getUnqual(EF->getParamPacketType()->getLLVMType());
116 llvm::FunctionType* HelperFunctionType;
117 std::vector<const llvm::Type*> Params;
118
119 Params.push_back(HelperFunctionParameterTypeP);
120 HelperFunctionType = llvm::FunctionType::get(F->getReturnType(), Params, false);
121
122 HelperFunction = llvm::Function::Create(HelperFunctionType, llvm::GlobalValue::ExternalLinkage, HelperFunctionName, mpModule);
123
124 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
125 HelperFunction->setCallingConv(F->getCallingConv());
126
127 /* Create helper function body */
128 {
129 llvm::Argument* HelperFunctionParameter = &(*HelperFunction->arg_begin());
130 llvm::BasicBlock* BB = llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
131 llvm::IRBuilder<>* IB = new llvm::IRBuilder<>(BB);
132 llvm::SmallVector<llvm::Value*, 6> Params;
133 llvm::Value* Idx[2];
134
135 Idx[0] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
136
137 /* getelementptr and load instruction for all elements in parameter .p */
138 for(int i=0;i<EF->getNumParameters();i++) {
139 /* getelementptr */
140 Idx[1] = llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), i);
141 llvm::Value* Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter, Idx, Idx + 2);
142 /* load */
143 llvm::Value* V = IB->CreateLoad(Ptr);
144 Params.push_back(V);
145 }
146
147 /* call and pass the all elements as paramter to F */
148 llvm::CallInst* CI = IB->CreateCall(F, Params.data(), Params.data() + Params.size());
149 CI->setCallingConv(F->getCallingConv());
150
151 if(F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
152 IB->CreateRetVoid();
153 else
154 IB->CreateRet(CI);
155
156 delete IB;
157 }
158 }
159
160 ExportFuncInfo.push_back( llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()) );
161 }
162
163 mExportFuncMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportFuncInfo.data(), ExportFuncInfo.size()) );
164
165 ExportFuncInfo.clear();
166 }
167 }
168
169 /* Dump export type info */
170 if(mContext->hasExportType()) {
171 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
172
173 for(RSContext::const_export_type_iterator I = mContext->export_types_begin();
174 I != mContext->export_types_end();
175 I++)
176 {
177 /* First, dump type name list to export */
178 const RSExportType* ET = I->getValue();
179
180 ExportTypeInfo.clear();
181 /* type name */
182 ExportTypeInfo.push_back( llvm::MDString::get(mLLVMContext, ET->getName().c_str()) );
183
184 if(ET->getClass() == RSExportType::ExportClassRecord) {
185 const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
186
187 if(mExportTypeMetadata == NULL)
188 mExportTypeMetadata = llvm::NamedMDNode::Create(mLLVMContext, "#rs_export_type", NULL, 0, mpModule);
189
190 mExportTypeMetadata->addOperand( llvm::MDNode::get(mLLVMContext, ExportTypeInfo.data(), ExportTypeInfo.size()) );
191
192 /* Now, export struct field information to %[struct name] */
193 std::string StructInfoMetadataName = "%" + ET->getName();
194 llvm::NamedMDNode* StructInfoMetadata = llvm::NamedMDNode::Create(mLLVMContext, StructInfoMetadataName.c_str(), NULL, 0, mpModule);
195 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
196
197 assert(StructInfoMetadata->getNumOperands() == 0 && "Metadata with same name was created before");
198 for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
199 FI != ERT->fields_end();
200 FI++)
201 {
202 const RSExportRecordType::Field* F = *FI;
203
204 /* 1. field name */
205 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getName().c_str()) );
206 /* 2. field type name */
207 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, F->getType()->getName().c_str()) );
208
209 /* 3. field kind */
210 switch(F->getType()->getClass()) {
211 case RSExportType::ExportClassPrimitive:
212 case RSExportType::ExportClassVector:
213 {
214 RSExportPrimitiveType* EPT = (RSExportPrimitiveType*) F->getType();
215 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(EPT->getKind())) );
216 }
217 break;
218
219 default:
220 FieldInfo.push_back( llvm::MDString::get(mLLVMContext, llvm::itostr(RSExportPrimitiveType::DataKindUser)) );
221 break;
222 }
223
224 StructInfoMetadata->addOperand( llvm::MDNode::get(mLLVMContext, FieldInfo.data(), FieldInfo.size()) );
225
226 FieldInfo.clear();
227 }
228 } /* ET->getClass() == RSExportType::ExportClassRecord */
229 }
230 }
231
232 return;
233}
234
235RSBackend::~RSBackend() {
236 return;
237}
238
239} /* namespace slang */