blob: 52494838f48dd326e55ace0c79ceff30381437fd [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#include "slang.hpp"
2#include "slang_backend.hpp"
3
4#include "llvm/Module.h" /* for class llvm::Module */
5#include "llvm/Metadata.h" /* for class llvm::NamedMDNode */
6#include "llvm/LLVMContext.h" /* for llvm::getGlobalContext() */
7
8#include "llvm/Target/TargetMachine.h" /* for class llvm::TargetMachine and llvm::TargetMachine::AssemblyFile */
9#include "llvm/Target/TargetOptions.h" /* for
10 * variable bool llvm::UseSoftFloat
11 * FloatABI::ABIType llvm::FloatABIType
12 * bool llvm::NoZerosInBSS
13 */
14#include "llvm/Target/TargetRegistry.h" /* for class llvm::TargetRegistry */
15#include "llvm/Target/SubtargetFeature.h" /* for class llvm::SubtargetFeature */
16
17#include "llvm/CodeGen/RegAllocRegistry.h" /* for class llvm::RegisterRegAlloc */
18#include "llvm/CodeGen/SchedulerRegistry.h" /* for class llvm::RegisterScheduler and llvm::createDefaultScheduler() */
19
20#include "llvm/Assembly/PrintModulePass.h" /* for function createPrintModulePass() */
21#include "llvm/Bitcode/ReaderWriter.h" /* for function createBitcodeWriterPass() */
22
23#include "clang/AST/Decl.h" /* for class clang::*Decl */
Shih-wei Liao462aefd2010-06-04 15:32:04 -070024#include "clang/AST/DeclGroup.h" /* for class clang::DeclGroupRef */
25#include "clang/AST/ASTContext.h" /* for class clang::ASTContext */
26
27#include "clang/Basic/TargetInfo.h" /* for class clang::TargetInfo */
28#include "clang/Basic/Diagnostic.h" /* for class clang::Diagnostic */
29#include "clang/Basic/TargetOptions.h" /* for class clang::TargetOptions */
30
31#include "clang/Frontend/FrontendDiagnostic.h" /* for clang::diag::* */
32
33#include "clang/CodeGen/ModuleBuilder.h" /* for class clang::CodeGenerator */
34#include "clang/CodeGen/CodeGenOptions.h" /* for class clang::CodeGenOptions */
35
Shih-wei Liao462aefd2010-06-04 15:32:04 -070036namespace slang {
37
38bool Backend::CreateCodeGenPasses() {
39 if(mOutputType != SlangCompilerOutput_Assembly && mOutputType != SlangCompilerOutput_Obj)
40 return true;
41
42 /* Now we add passes for code emitting */
43 if(mCodeGenPasses) {
44 return true;
45 } else {
46 mCodeGenPasses = new llvm::FunctionPassManager(mpModule);
47 mCodeGenPasses->add(new llvm::TargetData(*mpTargetData));
48 }
49
50 /* Create the TargetMachine for generating code. */
51 std::string Triple = mpModule->getTargetTriple();
52
53 std::string Error;
54 const llvm::Target* TargetInfo = llvm::TargetRegistry::lookupTarget(Triple, Error);
55 if(TargetInfo == NULL) {
56 mDiags.Report(clang::diag::err_fe_unable_to_create_target) << Error;
57 return false;
58 }
59
60 llvm::NoFramePointerElim = mCodeGenOpts.DisableFPElim;
61
62 /*
63 * Use hardware FPU.
64 *
65 * FIXME: Need to detect the CPU capability and decide whether to use softfp. To use softfp, change following 2 lines to
66 *
67 * llvm::FloatABIType = llvm::FloatABI::Soft;
68 * llvm::UseSoftFloat = true;
69 */
70 llvm::FloatABIType = llvm::FloatABI::Hard;
71 llvm::UseSoftFloat = false;
72
73 llvm::TargetMachine::setRelocationModel(llvm::Reloc::Static); /* ACC needs all unknown symbols resolved at compilation time.
74 So we don't need any relocation model. */
75
76 /* The target with pointer size greater than 32 (e.g. x86_64 architecture) may need large data address model */
77 if(mpTargetData->getPointerSizeInBits() > 32)
78 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Medium);
79 else
80 llvm::TargetMachine::setCodeModel(llvm::CodeModel::Small); /* This is set for the linker (specify how large of the virtual addresses
81 we can access for all unknown symbols.) */
82
83 /* setup feature string */
84 std::string FeaturesStr;
85 if(mTargetOpts.CPU.size() || mTargetOpts.Features.size()) {
86 llvm::SubtargetFeatures Features;
87
88 Features.setCPU(mTargetOpts.CPU);
89
90 for(std::vector<std::string>::const_iterator it = mTargetOpts.Features.begin();
91 it != mTargetOpts.Features.end();
92 it++)
93 Features.AddFeature(*it);
94
95 FeaturesStr = Features.getString();
96 }
97 llvm::TargetMachine *TM = TargetInfo->createTargetMachine(Triple, FeaturesStr);
98
99 /* Register scheduler */
100 llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
101
102 /* Register allocation policy:
103 * createLocalRegisterAllocator: fast but bad quality
104 * createLinearScanRegisterAllocator: not so fast but good quality
105 */
106 llvm::RegisterRegAlloc::setDefault((mCodeGenOpts.OptimizationLevel == 0) ? llvm::createLocalRegisterAllocator : llvm::createLinearScanRegisterAllocator);
107
108 llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default;
109 if(mCodeGenOpts.OptimizationLevel == 0)
110 OptLevel = llvm::CodeGenOpt::None;
111 else if(mCodeGenOpts.OptimizationLevel == 3)
112 OptLevel = llvm::CodeGenOpt::Aggressive;
113
114 llvm::TargetMachine::CodeGenFileType CGFT = llvm::TargetMachine::CGFT_AssemblyFile;;
115 if(mOutputType == SlangCompilerOutput_Obj)
116 CGFT = llvm::TargetMachine::CGFT_ObjectFile;
117 if(TM->addPassesToEmitFile(*mCodeGenPasses, FormattedOutStream, CGFT, OptLevel)) {
118 mDiags.Report(clang::diag::err_fe_unable_to_interface_with_target);
119 return false;
120 }
121
122 return true;
123}
124
125Backend::Backend(Diagnostic &Diags,
126 const CodeGenOptions& CodeGenOpts,
127 const TargetOptions& TargetOpts,
128 const PragmaList& Pragmas,
129 llvm::raw_ostream* OS,
Kirk Stewart6b226742010-06-11 10:51:12 -0700130 SlangCompilerOutputTy OutputType,
Kirk Stewart1fd85792010-07-07 09:51:23 -0700131 SourceManager &SourceMgr,
132 bool AllowRSPrefix) :
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700133 ASTConsumer(),
134 mLLVMContext(llvm::getGlobalContext()),
135 mDiags(Diags),
136 mCodeGenOpts(CodeGenOpts),
137 mTargetOpts(TargetOpts),
138 mPragmas(Pragmas),
139 mpOS(OS),
140 mOutputType(OutputType),
141 mpModule(NULL),
142 mpTargetData(NULL),
143 mGen(NULL),
144 mPerFunctionPasses(NULL),
145 mPerModulePasses(NULL),
Kirk Stewart6b226742010-06-11 10:51:12 -0700146 mCodeGenPasses(NULL),
Kirk Stewart1fd85792010-07-07 09:51:23 -0700147 mSourceMgr(SourceMgr),
148 mAllowRSPrefix(AllowRSPrefix)
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700149{
150 FormattedOutStream.setStream(*mpOS, llvm::formatted_raw_ostream::PRESERVE_STREAM);
151 mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
152 return;
153}
154
155void Backend::Initialize(ASTContext &Ctx) {
156 mGen->Initialize(Ctx);
157
158 mpModule = mGen->GetModule();
159 mpTargetData = new llvm::TargetData(Slang::TargetDescription);
160
161 return;
162}
163
164void Backend::HandleTopLevelDecl(DeclGroupRef D) {
Kirk Stewart6b226742010-06-11 10:51:12 -0700165 /* Disallow user-defined functions with prefix "rs" */
Kirk Stewart1fd85792010-07-07 09:51:23 -0700166 if (!mAllowRSPrefix) {
167 DeclGroupRef::iterator it;
168 for (it = D.begin(); it != D.end(); it++) {
169 FunctionDecl *FD = dyn_cast<FunctionDecl>(*it);
170 if (!FD || !FD->isThisDeclarationADefinition()) continue;
171 if (FD->getName().startswith("rs")) {
172 mDiags.Report(FullSourceLoc(FD->getLocStart(), mSourceMgr),
173 mDiags.getCustomDiagID(Diagnostic::Error, "invalid function name prefix, \"rs\" is reserved: '%0'")) << FD->getNameAsString();
174 }
Kirk Stewart6b226742010-06-11 10:51:12 -0700175 }
176 }
177
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700178 mGen->HandleTopLevelDecl(D);
179 return;
180}
181
182void Backend::HandleTranslationUnit(ASTContext& Ctx) {
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700183 mGen->HandleTranslationUnit(Ctx);
184
185 /*
186 * Here, we complete a translation unit (whole translation unit is now in LLVM IR).
187 * Now, interact with LLVM backend to generate actual machine code (asm or machine
188 * code, whatever.)
189 */
190
191 if(!mpModule || !mpTargetData) /* Silently ignore if we weren't initialized for some reason. */
192 return;
193
194 llvm::Module* M = mGen->ReleaseModule();
195 if(!M) {
196 /* The module has been released by IR gen on failures, do not double free. */
197 mpModule = NULL;
198 return;
199 }
200
201 assert(mpModule == M && "Unexpected module change during LLVM IR generation");
202
203 /* Insert #pragma information into metadata section of module */
204 if(!mPragmas.empty()) {
205 llvm::NamedMDNode* PragmaMetadata = llvm::NamedMDNode::Create(mLLVMContext, Slang::PragmaMetadataName, NULL, 0, mpModule);
206 for(PragmaList::const_iterator it = mPragmas.begin();
207 it != mPragmas.end();
208 it++)
209 {
210 llvm::SmallVector<llvm::Value*, 2> Pragma;
211 /* Name goes first */
212 Pragma.push_back(llvm::MDString::get(mLLVMContext, it->first));
213 /* And then value */
214 Pragma.push_back(llvm::MDString::get(mLLVMContext, it->second));
215 /* Create MDNode and insert into PragmaMetadata */
216 PragmaMetadata->addOperand( llvm::MDNode::get(mLLVMContext, Pragma.data(), Pragma.size()) );
217 }
218 }
219
220 HandleTranslationUnitEx(Ctx);
221
222 /* Create passes for optimization and code emission */
223
224 /* Create and run per-function passes */
225 CreateFunctionPasses();
226 if(mPerFunctionPasses) {
227 mPerFunctionPasses->doInitialization();
228
229 for(llvm::Module::iterator I = mpModule->begin();
230 I != mpModule->end();
231 I++)
232 if(!I->isDeclaration())
233 mPerFunctionPasses->run(*I);
234
235 mPerFunctionPasses->doFinalization();
236 }
237
238
239 /* Create and run module passes */
240 CreateModulePasses();
241 if(mPerModulePasses)
242 mPerModulePasses->run(*mpModule);
243
244 switch(mOutputType) {
245 case SlangCompilerOutput_Assembly:
246 case SlangCompilerOutput_Obj:
247 if(!CreateCodeGenPasses())
248 return;
249
250 mCodeGenPasses->doInitialization();
251
252 for(llvm::Module::iterator I = mpModule->begin();
253 I != mpModule->end();
254 I++)
255 if(!I->isDeclaration())
256 mCodeGenPasses->run(*I);
257
258 mCodeGenPasses->doFinalization();
259 break;
260
261 case SlangCompilerOutput_LL:
262 {
263 llvm::PassManager* LLEmitPM = new llvm::PassManager();
264 LLEmitPM->add(llvm::createPrintModulePass(&FormattedOutStream));
265 LLEmitPM->run(*mpModule);
266 }
267 break;
268
269 case SlangCompilerOutput_Bitcode:
270 {
271 llvm::PassManager* BCEmitPM = new llvm::PassManager();
272 BCEmitPM->add(llvm::createBitcodeWriterPass(FormattedOutStream));
273 BCEmitPM->run(*mpModule);
274 }
275 break;
276
277 case SlangCompilerOutput_Nothing:
278 return;
279 break;
280
281 default:
282 assert(false && "Unknown output type");
283 break;
284 }
285
286 FormattedOutStream.flush();
287
288 return;
289}
290
291void Backend::HandleTagDeclDefinition(TagDecl* D) {
292 mGen->HandleTagDeclDefinition(D);
293 return;
294}
295
296void Backend::CompleteTentativeDefinition(VarDecl* D) {
297 mGen->CompleteTentativeDefinition(D);
298 return;
299}
300
301Backend::~Backend() {
302 if(mpModule)
303 delete mpModule;
304 if(mpTargetData)
305 delete mpTargetData;
306 if(mGen)
307 delete mGen;
308 if(mPerFunctionPasses)
309 delete mPerFunctionPasses;
310 if(mPerModulePasses)
311 delete mPerModulePasses;
312 if(mCodeGenPasses)
313 delete mCodeGenPasses;
314 return;
315}
316
317} /* namespace slang */