/* * Copyright 2015, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "bcinfo/BitcodeWrapper.h" #include "llvm/Support/raw_ostream.h" #include "BitWriter_2_9/ReaderWriter_2_9.h" #include "BitWriter_2_9_func/ReaderWriter_2_9_func.h" #include "BitWriter_3_2/ReaderWriter_3_2.h" #include "slang_assert.h" #include "slang_bitcode_gen.h" #include "slang_version.h" #include "llvm/Bitcode/ReaderWriter.h" namespace slang { void writeBitcode(llvm::raw_ostream &Out, const llvm::Module &M, uint32_t TargetAPI, uint32_t OptimizationLevel, bool GenerateDebugInfo) { std::string BitcodeStr; llvm::raw_string_ostream Bitcode(BitcodeStr); // The older bitcode writers will produce invalid bitcode if the -g // flag is set using WriteBitcodeToFile. As such we use the ToT writer // when -g is set. However, this will produce a bitcode file linked to // this version of LLVM as the debug info format can change between // versions. // If bcc receives a bitcode file with a format of debug info // which is either ahead or behind the version it is expecting it will // fail the verification stage. Failing this stage results in the bitcode // loader returning null and the compiler will terminate abruptly. Bitcode // files with debug info are as such only capable of targeting devices with // LLVM libraries with the same debug info version as the version of slang // which was used to compile the file. This is due to the fact that LLVM // offers no backwards or forwards compatibility guarantee for its debug // bitcode. At the moment the only practical guarantee which can be made // is that the debug bitcode emitted by any slang will work with the bcc // version which was newest at the time when llvm-rs-cc was built. if (GenerateDebugInfo) { llvm::WriteBitcodeToFile(&M, Bitcode); } else { // Create the bitcode. switch (TargetAPI) { case SLANG_HC_TARGET_API: case SLANG_HC_MR1_TARGET_API: case SLANG_HC_MR2_TARGET_API: { // Pre-ICS targets must use the LLVM 2.9 BitcodeWriter llvm_2_9::WriteBitcodeToFile(&M, Bitcode); break; } case SLANG_ICS_TARGET_API: case SLANG_ICS_MR1_TARGET_API: { // ICS targets must use the LLVM 2.9_func BitcodeWriter llvm_2_9_func::WriteBitcodeToFile(&M, Bitcode); break; } default: { if (TargetAPI != SLANG_DEVELOPMENT_TARGET_API && (TargetAPI < SLANG_MINIMUM_TARGET_API || TargetAPI > SLANG_MAXIMUM_TARGET_API)) { slangAssert(false && "Invalid target API value"); } // Switch to the 3.2 BitcodeWriter by default, and don't use // LLVM's included BitcodeWriter at all (for now). llvm_3_2::WriteBitcodeToFile(&M, Bitcode); break; } } } const uint32_t CompilerVersion = SlangVersion::CURRENT; // Create the bitcode wrapper. bcinfo::AndroidBitcodeWrapper Wrapper; size_t ActualWrapperLen = bcinfo::writeAndroidBitcodeWrapper( &Wrapper, Bitcode.str().length(), TargetAPI, CompilerVersion, OptimizationLevel); slangAssert(ActualWrapperLen > 0); // Write out the file. Out.write(reinterpret_cast(&Wrapper), ActualWrapperLen); Out << Bitcode.str(); } } // namespace slang