1 /*
2  * Copyright 2015, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "bcinfo/BitcodeWrapper.h"
18 
19 #include "llvm/Support/raw_ostream.h"
20 
21 #include "BitWriter_2_9/ReaderWriter_2_9.h"
22 #include "BitWriter_2_9_func/ReaderWriter_2_9_func.h"
23 #include "BitWriter_3_2/ReaderWriter_3_2.h"
24 
25 #include "slang_assert.h"
26 #include "slang_bitcode_gen.h"
27 #include "slang_version.h"
28 #include "llvm/Bitcode/ReaderWriter.h"
29 
30 namespace slang {
31 
writeBitcode(llvm::raw_ostream & Out,const llvm::Module & M,uint32_t TargetAPI,uint32_t OptimizationLevel,bool GenerateDebugInfo)32 void writeBitcode(llvm::raw_ostream &Out,
33                   const llvm::Module &M,
34                   uint32_t TargetAPI,
35                   uint32_t OptimizationLevel,
36                   bool GenerateDebugInfo) {
37   std::string BitcodeStr;
38   llvm::raw_string_ostream Bitcode(BitcodeStr);
39 
40   // The older bitcode writers will produce invalid bitcode if the -g
41   // flag is set using WriteBitcodeToFile. As such we use the ToT writer
42   // when -g is set. However, this will produce a bitcode file linked to
43   // this version of LLVM as the debug info format can change between
44   // versions.
45   // If bcc receives a bitcode file with a format of debug info
46   // which is either ahead or behind the version it is expecting it will
47   // fail the verification stage. Failing this stage results in the bitcode
48   // loader returning null and the compiler will terminate abruptly. Bitcode
49   // files with debug info are as such only capable of targeting devices with
50   // LLVM libraries with the same debug info version as the version of slang
51   // which was used to compile the file. This is due to the fact that LLVM
52   // offers no backwards or forwards compatibility guarantee for its debug
53   // bitcode. At the moment the only practical guarantee which can be made
54   // is that the debug bitcode emitted by any slang will work with the bcc
55   // version which was newest at the time when llvm-rs-cc was built.
56   if (GenerateDebugInfo) {
57     llvm::WriteBitcodeToFile(&M, Bitcode);
58   } else {
59     // Create the bitcode.
60     switch (TargetAPI) {
61     case SLANG_HC_TARGET_API:
62     case SLANG_HC_MR1_TARGET_API:
63     case SLANG_HC_MR2_TARGET_API: {
64       // Pre-ICS targets must use the LLVM 2.9 BitcodeWriter
65       llvm_2_9::WriteBitcodeToFile(&M, Bitcode);
66       break;
67     }
68     case SLANG_ICS_TARGET_API:
69     case SLANG_ICS_MR1_TARGET_API: {
70       // ICS targets must use the LLVM 2.9_func BitcodeWriter
71       llvm_2_9_func::WriteBitcodeToFile(&M, Bitcode);
72       break;
73     }
74     default: {
75       if (TargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
76           (TargetAPI < SLANG_MINIMUM_TARGET_API ||
77            TargetAPI > SLANG_MAXIMUM_TARGET_API)) {
78         slangAssert(false && "Invalid target API value");
79       }
80       // Switch to the 3.2 BitcodeWriter by default, and don't use
81       // LLVM's included BitcodeWriter at all (for now).
82       llvm_3_2::WriteBitcodeToFile(&M, Bitcode);
83       break;
84     }
85     }
86   }
87 
88   const uint32_t CompilerVersion = SlangVersion::CURRENT;
89 
90   // Create the bitcode wrapper.
91   bcinfo::AndroidBitcodeWrapper Wrapper;
92   size_t ActualWrapperLen = bcinfo::writeAndroidBitcodeWrapper(
93         &Wrapper, Bitcode.str().length(), TargetAPI,
94         CompilerVersion, OptimizationLevel);
95 
96   slangAssert(ActualWrapperLen > 0);
97 
98   // Write out the file.
99   Out.write(reinterpret_cast<char*>(&Wrapper), ActualWrapperLen);
100   Out << Bitcode.str();
101 }
102 
103 }  // namespace slang
104