/* APPLE LOCAL begin LLVM (ENTIRE FILE!) */ /* High-level LLVM backend interface Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by Chris Lattner (sabre@nondot.org) This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "llvm-internal.h" #include "llvm-debug.h" #include "llvm-file-ostream.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" #include "llvm/ValueSymbolTable.h" #include "llvm/Analysis/LoadValueNumbering.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/Writer.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachineRegistry.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/IPO.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Streams.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include #undef VISIBILITY_HIDDEN extern "C" { #include "config.h" #include "system.h" #include "coretypes.h" #include "flags.h" #include "tree.h" #include "diagnostic.h" #include "output.h" #include "toplev.h" #include "timevar.h" #include "tm.h" #include "function.h" #include "tree-inline.h" #include "langhooks.h" } // Non-zero if bytecode from PCH is successfully read. int flag_llvm_pch_read; // Global state for the LLVM backend. Module *TheModule = 0; DebugInfo *TheDebugInfo = 0; TargetMachine *TheTarget = 0; TypeConverter *TheTypeConverter = 0; llvm::OStream *AsmOutFile = 0; /// DisableLLVMOptimizations - Allow the user to specify: /// "-mllvm -disable-llvm-optzns" on the llvm-gcc command line to force llvm /// optimizations off. static cl::opt DisableLLVMOptimizations("disable-llvm-optzns"); std::vector > StaticCtors, StaticDtors; SmallSetVector AttributeUsedGlobals; std::vector AttributeNoinlineFunctions; std::vector AttributeAnnotateGlobals; /// PerFunctionPasses - This is the list of cleanup passes run per-function /// as each is compiled. In cases where we are not doing IPO, it includes the /// code generator. static FunctionPassManager *PerFunctionPasses = 0; static PassManager *PerModulePasses = 0; static FunctionPassManager *CodeGenPasses = 0; static void createOptimizationPasses(); void llvm_initialize_backend(void) { // Initialize LLVM options. std::vector Args; Args.push_back(progname); // program name // Allow targets to specify PIC options and other stuff to the corresponding // LLVM backends. #ifdef LLVM_SET_TARGET_OPTIONS LLVM_SET_TARGET_OPTIONS(Args); #endif if (time_report) Args.push_back("--time-passes"); if (fast_math_flags_set_p()) Args.push_back("--enable-unsafe-fp-math"); if (!flag_omit_frame_pointer) Args.push_back("--disable-fp-elim"); if (!flag_zero_initialized_in_bss) Args.push_back("--nozero-initialized-in-bss"); if (flag_debug_asm) Args.push_back("--asm-verbose"); if (flag_debug_pass_structure) Args.push_back("--debug-pass=Structure"); if (flag_debug_pass_arguments) Args.push_back("--debug-pass=Arguments"); if (flag_exceptions) Args.push_back("--enable-eh"); // If there are options that should be passed through to the LLVM backend // directly from the command line, do so now. This is mainly for debugging // purposes, and shouldn't really be for general use. std::vector ArgStrings; if (llvm_optns) { std::string Opts = llvm_optns; for (std::string Opt = getToken(Opts); !Opt.empty(); Opt = getToken(Opts)) ArgStrings.push_back(Opt); } for (unsigned i = 0, e = ArgStrings.size(); i != e; ++i) Args.push_back(ArgStrings[i].c_str()); Args.push_back(0); // Null terminator. int pseudo_argc = Args.size()-1; cl::ParseCommandLineOptions(pseudo_argc, (char**)&Args[0]); TheModule = new Module(""); // If the target wants to override the architecture, e.g. turning // powerpc-darwin-... into powerpc64-darwin-... when -m64 is enabled, do so // now. std::string TargetTriple = TARGET_NAME; #ifdef LLVM_OVERRIDE_TARGET_ARCH std::string Arch = LLVM_OVERRIDE_TARGET_ARCH(); if (!Arch.empty()) { std::string::size_type DashPos = TargetTriple.find('-'); if (DashPos != std::string::npos)// If we have a sane t-t, replace the arch. TargetTriple = Arch + TargetTriple.substr(DashPos); } #endif TheModule->setTargetTriple(TargetTriple); TheTypeConverter = new TypeConverter(); // Create the TargetMachine we will be generating code with. // FIXME: Figure out how to select the target and pass down subtarget info. std::string Err; const TargetMachineRegistry::Entry *TME = TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Err); if (!TME) { cerr << "Did not get a target machine!\n"; exit(1); } // Figure out the subtarget feature string we pass to the target. std::string FeatureStr; // The target can set LLVM_SET_SUBTARGET_FEATURES to configure the LLVM // backend. #ifdef LLVM_SET_SUBTARGET_FEATURES SubtargetFeatures Features; LLVM_SET_SUBTARGET_FEATURES(Features); FeatureStr = Features.getString(); #endif TheTarget = TME->CtorFn(*TheModule, FeatureStr); // Install information about target datalayout stuff into the module for // optimizer use. TheModule->setDataLayout(TheTarget->getTargetData()-> getStringRepresentation()); if (optimize) { RegisterScheduler::setDefault(createDefaultScheduler); } else { RegisterScheduler::setDefault(createBFS_DAGScheduler); } RegisterRegAlloc::setDefault(createLinearScanRegisterAllocator); if (!optimize && debug_info_level > DINFO_LEVEL_NONE) TheDebugInfo = new DebugInfo(TheModule); } void llvm_lang_dependent_init(const char *Name) { if (Name) TheModule->setModuleIdentifier(Name); } oFILEstream *AsmOutStream = 0; /// Read bytecode from PCH file. Initialize TheModule and setup /// LTypes vector. void llvm_pch_read(const unsigned char *Buffer, unsigned Size) { std::string ModuleName = TheModule->getModuleIdentifier(); if (TheModule) delete TheModule; clearTargetBuiltinCache(); MemoryBuffer *MB = MemoryBuffer::getNewMemBuffer(Size, ModuleName.c_str()); memcpy((char*)MB->getBufferStart(), Buffer, Size); std::string ErrMsg; TheModule = ParseBitcodeFile(MB, &ErrMsg); delete MB; if (!TheModule) { cerr << "Error reading bytecodes from PCH file\n"; cerr << ErrMsg << "\n"; exit(1); } if (PerFunctionPasses || PerModulePasses || CodeGenPasses) { delete PerFunctionPasses; delete PerModulePasses; delete CodeGenPasses; // Don't run codegen, when we should output PCH if (!flag_pch_file) createOptimizationPasses(); else llvm_pch_write_init(); } // Read LLVM Types string table readLLVMTypesStringTable(); readLLVMValues(); flag_llvm_pch_read = 1; } // Initialize PCH writing. void llvm_pch_write_init(void) { timevar_push(TV_LLVM_INIT); AsmOutStream = new oFILEstream(asm_out_file); AsmOutFile = new OStream(*AsmOutStream); PerModulePasses = new PassManager(); PerModulePasses->add(new TargetData(*TheTarget->getTargetData())); // Emit an LLVM .bc file to the output. This is used when passed // -emit-llvm -c to the GCC driver. PerModulePasses->add(CreateBitcodeWriterPass(*AsmOutStream)); // Disable emission of .ident into the output file... which is completely // wrong for llvm/.bc emission cases. flag_no_ident = 1; flag_llvm_pch_read = 0; timevar_pop(TV_LLVM_INIT); } static void createOptimizationPasses() { // Create and set up the per-function pass manager. // FIXME: Move the code generator to be function-at-a-time. PerFunctionPasses = new FunctionPassManager(new ExistingModuleProvider(TheModule)); PerFunctionPasses->add(new TargetData(*TheTarget->getTargetData())); // In -O0 if checking is disabled, we don't even have per-function passes. bool HasPerFunctionPasses = false; #ifdef ENABLE_CHECKING PerFunctionPasses->add(createVerifierPass()); HasPerFunctionPasses = true; #endif if (optimize > 0 && !DisableLLVMOptimizations) { HasPerFunctionPasses = true; PerFunctionPasses->add(createCFGSimplificationPass()); if (optimize == 1) PerFunctionPasses->add(createPromoteMemoryToRegisterPass()); else PerFunctionPasses->add(createScalarReplAggregatesPass()); PerFunctionPasses->add(createInstructionCombiningPass()); // PerFunctionPasses->add(createCFGSimplificationPass()); } // FIXME: AT -O0/O1, we should stream out functions at a time. PerModulePasses = new PassManager(); PerModulePasses->add(new TargetData(*TheTarget->getTargetData())); bool HasPerModulePasses = false; if (optimize > 0 && !DisableLLVMOptimizations) { HasPerModulePasses = true; PassManager *PM = PerModulePasses; if (flag_unit_at_a_time) PM->add(createRaiseAllocationsPass()); // call %malloc -> malloc inst PM->add(createCFGSimplificationPass()); // Clean up disgusting code PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas if (flag_unit_at_a_time) { PM->add(createGlobalOptimizerPass()); // Optimize out global vars PM->add(createGlobalDCEPass()); // Remove unused fns and globs PM->add(createIPConstantPropagationPass()); // IP Constant Propagation PM->add(createDeadArgEliminationPass()); // Dead argument elimination } PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE // DISABLE PREDSIMPLIFY UNTIL PR967 is fixed. //PM->add(createPredicateSimplifierPass()); // Canonicalize registers PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE if (flag_unit_at_a_time) PM->add(createPruneEHPass()); // Remove dead EH info if (optimize > 1) { if (flag_inline_trees > 1) // respect -fno-inline-functions PM->add(createFunctionInliningPass()); // Inline small functions if (flag_unit_at_a_time && !lang_hooks.flag_no_builtin()) PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations if (optimize > 2) PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args } PM->add(createTailDuplicationPass()); // Simplify cfg by copying code PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. PM->add(createCFGSimplificationPass()); // Merge & remove BBs PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas PM->add(createInstructionCombiningPass()); // Combine silly seq's PM->add(createCondPropagationPass()); // Propagate conditionals PM->add(createTailCallEliminationPass()); // Eliminate tail calls PM->add(createCFGSimplificationPass()); // Merge & remove BBs PM->add(createReassociatePass()); // Reassociate expressions PM->add(createLoopRotatePass()); // Rotate Loop PM->add(createLICMPass()); // Hoist loop invariants PM->add(createLoopUnswitchPass(optimize_size ? true : false)); PM->add(createInstructionCombiningPass()); // Clean up after LICM/reassoc PM->add(createIndVarSimplifyPass()); // Canonicalize indvars if (flag_unroll_loops) PM->add(createLoopUnrollPass()); // Unroll small loops PM->add(createInstructionCombiningPass()); // Clean up after the unroller PM->add(createGVNPass()); // Eliminate redundancies PM->add(createSCCPPass()); // Constant prop with SCCP // Run instcombine after redundancy elimination to exploit opportunities // opened up by them. PM->add(createInstructionCombiningPass()); PM->add(createCondPropagationPass()); // Propagate conditionals PM->add(createDeadStoreEliminationPass()); // Delete dead stores PM->add(createAggressiveDCEPass()); // SSA based 'Aggressive DCE' PM->add(createCFGSimplificationPass()); // Merge & remove BBs if (optimize > 1 && flag_unit_at_a_time) PM->add(createConstantMergePass()); // Merge dup global constants PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes } if (emit_llvm_bc) { // Emit an LLVM .bc file to the output. This is used when passed // -emit-llvm -c to the GCC driver. PerModulePasses->add(CreateBitcodeWriterPass(*AsmOutStream)); // Disable emission of .ident into the output file... which is completely // wrong for llvm/.bc emission cases. flag_no_ident = 1; HasPerModulePasses = true; } else if (emit_llvm) { // Emit an LLVM .ll file to the output. This is used when passed // -emit-llvm -S to the GCC driver. PerModulePasses->add(new PrintModulePass(AsmOutFile)); // Disable emission of .ident into the output file... which is completely // wrong for llvm/.bc emission cases. flag_no_ident = 1; HasPerModulePasses = true; } else { FunctionPassManager *PM; // If there are passes we have to run on the entire module, we do codegen // as a separate "pass" after that happens. // FIXME: This is disabled right now until bugs can be worked out. Reenable // this for fast -O0 compiles! if (HasPerModulePasses || 1) { CodeGenPasses = PM = new FunctionPassManager(new ExistingModuleProvider(TheModule)); PM->add(new TargetData(*TheTarget->getTargetData())); } else { // If there are no module-level passes that have to be run, we codegen as // each function is parsed. PM = PerFunctionPasses; HasPerFunctionPasses = true; } // Normal mode, emit a .s file by running the code generator. switch (TheTarget->addPassesToEmitFile(*PM, *AsmOutStream, TargetMachine::AssemblyFile, /*FAST*/optimize == 0)) { default: case FileModel::Error: cerr << "Error interfacing to target machine!\n"; exit(1); case FileModel::AsmFile: break; } if (TheTarget->addPassesToEmitFileFinish(*PM, 0, /*Fast*/optimize == 0)) { cerr << "Error interfacing to target machine!\n"; exit(1); } } if (HasPerFunctionPasses) { PerFunctionPasses->doInitialization(); } else { delete PerFunctionPasses; PerFunctionPasses = 0; } if (!HasPerModulePasses) { delete PerModulePasses; PerModulePasses = 0; } } // llvm_asm_file_start - Start the .s file. void llvm_asm_file_start(void) { timevar_push(TV_LLVM_INIT); AsmOutStream = new oFILEstream(asm_out_file); AsmOutFile = new OStream(*AsmOutStream); flag_llvm_pch_read = 0; createOptimizationPasses(); AttributeUsedGlobals.clear(); timevar_pop(TV_LLVM_INIT); } /// ConvertStructorsList - Convert a list of static ctors/dtors to an /// initializer suitable for the llvm.global_[cd]tors globals. static void CreateStructorsList(std::vector > &Tors, const char *Name) { std::vector InitList; std::vector StructInit; StructInit.resize(2); for (unsigned i = 0, e = Tors.size(); i != e; ++i) { StructInit[0] = ConstantInt::get(Type::Int32Ty, Tors[i].second); StructInit[1] = Tors[i].first; InitList.push_back(ConstantStruct::get(StructInit, false)); } Constant *Array = ConstantArray::get(ArrayType::get(InitList[0]->getType(), InitList.size()), InitList); new GlobalVariable(Array->getType(), false, GlobalValue::AppendingLinkage, Array, Name, TheModule); } // llvm_asm_file_end - Finish the .s file. void llvm_asm_file_end(void) { timevar_push(TV_LLVM_PERFILE); llvm_shutdown_obj X; // Call llvm_shutdown() on exit. if (flag_pch_file) { writeLLVMTypesStringTable(); writeLLVMValues(); } // Add an llvm.global_ctors global if needed. if (!StaticCtors.empty()) CreateStructorsList(StaticCtors, "llvm.global_ctors"); // Add an llvm.global_dtors global if needed. if (!StaticDtors.empty()) CreateStructorsList(StaticDtors, "llvm.global_dtors"); if (!AttributeUsedGlobals.empty()) { std::vector AUGs; const Type *SBP= PointerType::get(Type::Int8Ty); for (SmallSetVector::iterator AI = AttributeUsedGlobals.begin(), AE = AttributeUsedGlobals.end(); AI != AE; ++AI) { Constant *C = *AI; AUGs.push_back(ConstantExpr::getBitCast(C, SBP)); } ArrayType *AT = ArrayType::get(SBP, AUGs.size()); Constant *Init = ConstantArray::get(AT, AUGs); GlobalValue* gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, "llvm.used", TheModule); gv->setSection("llvm.metadata"); AttributeUsedGlobals.clear(); } // Add llvm.noinline if (!AttributeNoinlineFunctions.empty()) { const Type *SBP= PointerType::get(Type::Int8Ty); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); Constant *Init = ConstantArray::get(AT, AttributeNoinlineFunctions); GlobalValue *gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, "llvm.noinline", TheModule); gv->setSection("llvm.metadata"); // Clear vector AttributeNoinlineFunctions.clear(); } // Add llvm.global.annotations if (!AttributeAnnotateGlobals.empty()) { Constant *Array = ConstantArray::get(ArrayType::get(AttributeAnnotateGlobals[0]->getType(), AttributeAnnotateGlobals.size()), AttributeAnnotateGlobals); GlobalValue *gv = new GlobalVariable(Array->getType(), false, GlobalValue::AppendingLinkage, Array, "llvm.global.annotations", TheModule); gv->setSection("llvm.metadata"); AttributeAnnotateGlobals.clear(); } // Finish off the per-function pass. if (PerFunctionPasses) PerFunctionPasses->doFinalization(); // Run module-level optimizers, if any are present. if (PerModulePasses) PerModulePasses->run(*TheModule); // Run the code generator, if present. if (CodeGenPasses) { CodeGenPasses->doInitialization(); for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E; ++I) if (!I->isDeclaration()) CodeGenPasses->run(*I); CodeGenPasses->doFinalization(); } AsmOutStream->flush(); fflush(asm_out_file); delete AsmOutStream; AsmOutStream = 0; delete AsmOutFile; AsmOutFile = 0; timevar_pop(TV_LLVM_PERFILE); } // llvm_emit_code_for_current_function - Top level interface for emitting a // function to the .s file. void llvm_emit_code_for_current_function(tree fndecl) { if (cfun->nonlocal_goto_save_area) sorry("%Jnon-local gotos not supported by LLVM", fndecl); if (errorcount || sorrycount) { TREE_ASM_WRITTEN(fndecl) = 1; return; // Do not process broken code. } timevar_push(TV_LLVM_FUNCS); // Convert the AST to raw/ugly LLVM code. Function *Fn; { TreeToLLVM Emitter(fndecl); // Set up parameters and prepare for return, for the function. Emitter.StartFunctionBody(); // Emit the body of the function. Emitter.Emit(DECL_SAVED_TREE(fndecl), 0); // Wrap things up. Fn = Emitter.FinishFunctionBody(); } #if 0 if (dump_file) { fprintf (dump_file, "\n\n;;\n;; Full LLVM generated for this function:\n;;\n"); Fn->dump(); } #endif if (PerFunctionPasses) PerFunctionPasses->run(*Fn); // TODO: Nuke the .ll code for the function at -O[01] if we don't want to // inline it or something else. // There's no need to defer outputting this function any more; we // know we want to output it. DECL_DEFER_OUTPUT(fndecl) = 0; // Finally, we have written out this function! TREE_ASM_WRITTEN(fndecl) = 1; timevar_pop(TV_LLVM_FUNCS); } // emit_alias_to_llvm - Given decl and target emit alias to target. void emit_alias_to_llvm(tree decl, tree target, tree target_decl) { if (errorcount || sorrycount) return; timevar_push(TV_LLVM_GLOBALS); // Get or create LLVM global for our alias. GlobalValue *V = cast(DECL_LLVM(decl)); GlobalValue *Aliasee = NULL; if (target_decl) Aliasee = cast(DECL_LLVM(target_decl)); else { // This is something insane. Probably only LTHUNKs can be here // Try to grab decl from IDENTIFIER_NODE // Query SymTab for aliasee const char* AliaseeName = IDENTIFIER_POINTER(target); Aliasee = dyn_cast_or_null(TheModule-> getValueSymbolTable().lookup(AliaseeName)); // Last resort. Query for name set via __asm__ if (!Aliasee) { std::string starred = std::string("\001") + AliaseeName; Aliasee = dyn_cast_or_null(TheModule-> getValueSymbolTable().lookup(starred)); } if (!Aliasee) { error ("%J%qD aliased to undefined symbol %qE", decl, decl, target); timevar_pop(TV_LLVM_GLOBALS); return; } } GlobalValue::LinkageTypes Linkage; // Check for external weak linkage if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) Linkage = GlobalValue::WeakLinkage; else if (!TREE_PUBLIC(decl)) Linkage = GlobalValue::InternalLinkage; else Linkage = GlobalValue::ExternalLinkage; GlobalAlias* GA = new GlobalAlias(Aliasee->getType(), Linkage, "", Aliasee, TheModule); // Handle visibility style if (TREE_PUBLIC(decl)) { if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) GA->setVisibility(GlobalValue::HiddenVisibility); else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) GA->setVisibility(GlobalValue::ProtectedVisibility); } if (V->getType() == GA->getType()) V->replaceAllUsesWith(GA); else if (!V->use_empty()) { error ("%J Alias %qD used with invalid type!", decl, decl); timevar_pop(TV_LLVM_GLOBALS); return; } changeLLVMValue(V, GA); GA->takeName(V); if (GlobalVariable *GV = dyn_cast(V)) GV->eraseFromParent(); else if (GlobalAlias *GA = dyn_cast(V)) GA->eraseFromParent(); else if (Function *F = dyn_cast(V)) F->eraseFromParent(); else assert(0 && "Unsupported global value"); TREE_ASM_WRITTEN(decl) = 1; timevar_pop(TV_LLVM_GLOBALS); return; } // Convert string to global value. Use existing global if possible. Constant* ConvertMetadataStringToGV(const char *str) { Constant *Init = ConstantArray::get(std::string(str)); // Use cached string if it exists. static std::map StringCSTCache; GlobalVariable *&Slot = StringCSTCache[Init]; if (Slot) return Slot; // Create a new string global. GlobalVariable *GV = new GlobalVariable(Init->getType(), true, GlobalVariable::InternalLinkage, Init, ".str", TheModule); GV->setSection("llvm.metadata"); Slot = GV; return GV; } /// AddAnnotateAttrsToGlobal - Adds decls that have a /// annotate attribute to a vector to be emitted later. void AddAnnotateAttrsToGlobal(GlobalValue *GV, tree decl) { // Handle annotate attribute on global. tree annotateAttr = lookup_attribute("annotate", DECL_ATTRIBUTES (decl)); // Get file and line number Constant *lineNo = ConstantInt::get(Type::Int32Ty, DECL_SOURCE_LINE(decl)); Constant *file = ConvertMetadataStringToGV(DECL_SOURCE_FILE(decl)); const Type *SBP= PointerType::get(Type::Int8Ty); file = ConstantExpr::getBitCast(file, SBP); // There may be multiple annotate attributes. Pass return of lookup_attr // to successive lookups. while (annotateAttr) { // Each annotate attribute is a tree list. // Get value of list which is our linked list of args. tree args = TREE_VALUE(annotateAttr); // Each annotate attribute may have multiple args. // Treat each arg as if it were a separate annotate attribute. for (tree a = args; a; a = TREE_CHAIN(a)) { // Each element of the arg list is a tree list, so get value tree val = TREE_VALUE(a); // Assert its a string, and then get that string. assert(TREE_CODE(val) == STRING_CST && "Annotate attribute arg should always be a string"); Constant *strGV = TreeConstantToLLVM::EmitLV_STRING_CST(val); Constant *Element[4] = {ConstantExpr::getBitCast(GV,SBP), ConstantExpr::getBitCast(strGV,SBP), file, lineNo}; AttributeAnnotateGlobals.push_back(ConstantStruct::get(Element, 4, false)); } // Get next annotate attribute. annotateAttr = TREE_CHAIN(annotateAttr); if (annotateAttr) annotateAttr = lookup_attribute("annotate", annotateAttr); } } /// emit_global_to_llvm - Emit the specified VAR_DECL or aggregate CONST_DECL to /// LLVM as a global variable. This function implements the end of /// assemble_variable. void emit_global_to_llvm(tree decl) { if (errorcount || sorrycount) return; // FIXME: Support alignment on globals: DECL_ALIGN. // FIXME: DECL_PRESERVE_P indicates the var is marked with attribute 'used'. // Global register variables don't turn into LLVM GlobalVariables. if (TREE_CODE(decl) == VAR_DECL && DECL_REGISTER(decl)) return; timevar_push(TV_LLVM_GLOBALS); // Get or create the global variable now. GlobalVariable *GV = cast(DECL_LLVM(decl)); // Convert the initializer over. Constant *Init; if (DECL_INITIAL(decl) == 0 || DECL_INITIAL(decl) == error_mark_node) { // This global should be zero initialized. Reconvert the type in case the // forward def of the global and the real def differ in type (e.g. declared // as 'int A[]', and defined as 'int A[100]'). Init = Constant::getNullValue(ConvertType(TREE_TYPE(decl))); } else { assert((TREE_CONSTANT(DECL_INITIAL(decl)) || TREE_CODE(DECL_INITIAL(decl)) == STRING_CST) && "Global initializer should be constant!"); // Temporarily set an initializer for the global, so we don't infinitely // recurse. If we don't do this, we can hit cases where we see "oh a global // with an initializer hasn't been initialized yet, call emit_global_to_llvm // on it". When constructing the initializer it might refer to itself. // this can happen for things like void *G = &G; // GV->setInitializer(UndefValue::get(GV->getType()->getElementType())); Init = TreeConstantToLLVM::Convert(DECL_INITIAL(decl)); } // If we had a forward definition that has a type that disagrees with our // initializer, insert a cast now. This sort of thing occurs when we have a // global union, and the LLVM type followed a union initializer that is // different from the union element used for the type. if (GV->getType()->getElementType() != Init->getType()) { GV->removeFromParent(); GlobalVariable *NGV = new GlobalVariable(Init->getType(), GV->isConstant(), GlobalValue::ExternalLinkage, 0, GV->getName(), TheModule); GV->replaceAllUsesWith(ConstantExpr::getBitCast(NGV, GV->getType())); if (AttributeUsedGlobals.count(GV)) { AttributeUsedGlobals.remove(GV); AttributeUsedGlobals.insert(NGV); } delete GV; SET_DECL_LLVM(decl, NGV); GV = NGV; } // Set the initializer. GV->setInitializer(Init); // Set thread local (TLS) if (TREE_CODE(decl) == VAR_DECL && DECL_THREAD_LOCAL(decl)) GV->setThreadLocal(true); // Set the linkage. if (!TREE_PUBLIC(decl)) { GV->setLinkage(GlobalValue::InternalLinkage); } else if (DECL_WEAK(decl) || DECL_ONE_ONLY(decl) || (DECL_COMMON(decl) && // DECL_COMMON is only meaningful if no init (!DECL_INITIAL(decl) || DECL_INITIAL(decl) == error_mark_node))) { // llvm-gcc also includes DECL_VIRTUAL_P here. GV->setLinkage(GlobalValue::WeakLinkage); } else if (DECL_COMDAT(decl)) { GV->setLinkage(GlobalValue::LinkOnceLinkage); } #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(GV,decl); #endif /* TARGET_ADJUST_LLVM_LINKAGE */ // Handle visibility style if (TREE_PUBLIC(decl)) { if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) GV->setVisibility(GlobalValue::HiddenVisibility); else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) GV->setVisibility(GlobalValue::ProtectedVisibility); } // Set the section for the global. if (TREE_CODE(decl) == VAR_DECL || TREE_CODE(decl) == CONST_DECL) { if (DECL_SECTION_NAME(decl)) { GV->setSection(TREE_STRING_POINTER(DECL_SECTION_NAME(decl))); #ifdef LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION } else if (const char *Section = LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION(decl)) { GV->setSection(Section); #endif } // Set the alignment for the global if one of the following condition is met // 1) DECL_ALIGN_UNIT does not match alignment as per ABI specification // 2) DECL_ALIGN is set by user. if (DECL_ALIGN_UNIT(decl)) { unsigned TargetAlign = getTargetData().getABITypeAlignment(GV->getType()->getElementType()); if (DECL_USER_ALIGN(decl) || TargetAlign != DECL_ALIGN_UNIT(decl)) GV->setAlignment(DECL_ALIGN_UNIT(decl)); } // Handle used decls if (DECL_PRESERVE_P (decl)) AttributeUsedGlobals.insert(GV); // Add annotate attributes for globals if (DECL_ATTRIBUTES(decl)) AddAnnotateAttrsToGlobal(GV, decl); } if (TheDebugInfo) TheDebugInfo->EmitGlobalVariable(GV, decl); timevar_pop(TV_LLVM_GLOBALS); } /// ValidateRegisterVariable - Check that a static "asm" variable is /// well-formed. If not, emit error messages and return true. If so, return /// false. bool ValidateRegisterVariable(tree decl) { const char *Name = IDENTIFIER_POINTER(DECL_ASSEMBLER_NAME(decl)); int RegNumber = decode_reg_name(Name); const Type *Ty = ConvertType(TREE_TYPE(decl)); // If this has already been processed, don't emit duplicate error messages. if (DECL_LLVM_SET_P(decl)) { // Error state encoded into DECL_LLVM. return cast(DECL_LLVM(decl))->getZExtValue(); } /* Detect errors in declaring global registers. */ if (RegNumber == -1) error("%Jregister name not specified for %qD", decl, decl); else if (RegNumber < 0) error("%Jinvalid register name for %qD", decl, decl); else if (TYPE_MODE(TREE_TYPE(decl)) == BLKmode) error("%Jdata type of %qD isn%'t suitable for a register", decl, decl); #if 0 // FIXME: enable this. else if (!HARD_REGNO_MODE_OK(RegNumber, TYPE_MODE(TREE_TYPE(decl)))) error("%Jregister specified for %qD isn%'t suitable for data type", decl, decl); #endif else if (DECL_INITIAL(decl) != 0 && TREE_STATIC(decl)) error("global register variable has initial value"); else if (!Ty->isFirstClassType()) sorry("%JLLVM cannot handle register variable %qD, report a bug", decl, decl); else { if (TREE_THIS_VOLATILE(decl)) warning("volatile register variables don%'t work as you might wish"); SET_DECL_LLVM(decl, ConstantInt::getFalse()); return false; // Everything ok. } SET_DECL_LLVM(decl, ConstantInt::getTrue()); return true; } // make_decl_llvm - Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL // should have static storage duration. In other words, it should not be an // automatic variable, including PARM_DECLs. // // There is, however, one exception: this function handles variables explicitly // placed in a particular register by the user. // // This function corresponds to make_decl_rtl in varasm.c, and is implicitly // called by DECL_LLVM if a decl doesn't have an LLVM set. // void make_decl_llvm(tree decl) { #ifdef ENABLE_CHECKING // Check that we are not being given an automatic variable. // A weak alias has TREE_PUBLIC set but not the other bits. if (TREE_CODE(decl) == PARM_DECL || TREE_CODE(decl) == RESULT_DECL || (TREE_CODE(decl) == VAR_DECL && !TREE_STATIC(decl) && !TREE_PUBLIC(decl) && !DECL_EXTERNAL(decl) && !DECL_REGISTER(decl))) abort(); // And that we were not given a type or a label. */ else if (TREE_CODE(decl) == TYPE_DECL || TREE_CODE(decl) == LABEL_DECL) abort (); #endif // For a duplicate declaration, we can be called twice on the // same DECL node. Don't discard the LLVM already made. if (DECL_LLVM_SET_P(decl)) return; if (errorcount || sorrycount) return; // Do not process broken code. // Global register variable with asm name, e.g.: // register unsigned long esp __asm__("ebp"); if (TREE_CODE(decl) != FUNCTION_DECL && DECL_REGISTER(decl)) { // This just verifies that the variable is ok. The actual "load/store" // code paths handle accesses to the variable. ValidateRegisterVariable(decl); return; } timevar_push(TV_LLVM_GLOBALS); const char *Name = ""; if (DECL_NAME(decl)) if (tree AssemblerName = DECL_ASSEMBLER_NAME(decl)) Name = IDENTIFIER_POINTER(AssemblerName); // Now handle ordinary static variables and functions (in memory). // Also handle vars declared register invalidly. if (Name[0] == 1) { #ifdef REGISTER_PREFIX if (strlen (REGISTER_PREFIX) != 0) { int reg_number = decode_reg_name(Name); if (reg_number >= 0 || reg_number == -3) error("%Jregister name given for non-register variable %qD", decl, decl); } #endif } // Specifying a section attribute on a variable forces it into a // non-.bss section, and thus it cannot be common. if (TREE_CODE(decl) == VAR_DECL && DECL_SECTION_NAME(decl) != NULL_TREE && DECL_INITIAL(decl) == NULL_TREE && DECL_COMMON(decl)) DECL_COMMON(decl) = 0; // Variables can't be both common and weak. if (TREE_CODE(decl) == VAR_DECL && DECL_WEAK(decl)) DECL_COMMON(decl) = 0; // Okay, now we need to create an LLVM global variable or function for this // object. Note that this is quite possibly a forward reference to the // object, so its type may change later. if (TREE_CODE(decl) == FUNCTION_DECL) { assert(Name[0] && "Function with empty name!"); // If this function has already been created, reuse the decl. This happens // when we have something like __builtin_memset and memset in the same file. Function *FnEntry = TheModule->getFunction(Name); if (FnEntry == 0) { unsigned CC; const FunctionType *Ty = TheTypeConverter->ConvertFunctionType(TREE_TYPE(decl), decl, NULL, CC); FnEntry = new Function(Ty, Function::ExternalLinkage, Name, TheModule); FnEntry->setCallingConv(CC); // Check for external weak linkage if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) FnEntry->setLinkage(Function::ExternalWeakLinkage); #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(FnEntry,decl); #endif /* TARGET_ADJUST_LLVM_LINKAGE */ // Handle visibility style if (TREE_PUBLIC(decl)) { if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) FnEntry->setVisibility(GlobalValue::HiddenVisibility); else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) FnEntry->setVisibility(GlobalValue::ProtectedVisibility); } assert(FnEntry->getName() == Name &&"Preexisting fn with the same name!"); } SET_DECL_LLVM(decl, FnEntry); } else { assert((TREE_CODE(decl) == VAR_DECL || TREE_CODE(decl) == CONST_DECL) && "Not a function or var decl?"); const Type *Ty = ConvertType(TREE_TYPE(decl)); GlobalVariable *GV ; // If we have "extern void foo", make the global have type {} instead of // type void. if (Ty == Type::VoidTy) Ty = StructType::get(std::vector(), false); if (Name[0] == 0) { // Global has no name. GV = new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage, 0, "", TheModule); // Check for external weak linkage if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) GV->setLinkage(GlobalValue::ExternalWeakLinkage); #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(GV,decl); #endif /* TARGET_ADJUST_LLVM_LINKAGE */ // Handle visibility style if (TREE_PUBLIC(decl)) { if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) GV->setVisibility(GlobalValue::HiddenVisibility); else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) GV->setVisibility(GlobalValue::ProtectedVisibility); } } else { // If the global has a name, prevent multiple vars with the same name from // being created. GlobalVariable *GVE = TheModule->getGlobalVariable(Name); if (GVE == 0) { GV = new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage,0, Name, TheModule); // Check for external weak linkage if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) GV->setLinkage(GlobalValue::ExternalWeakLinkage); #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(GV,decl); #endif /* TARGET_ADJUST_LLVM_LINKAGE */ // Handle visibility style if (TREE_PUBLIC(decl)) { if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) GV->setVisibility(GlobalValue::HiddenVisibility); else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) GV->setVisibility(GlobalValue::ProtectedVisibility); } // If GV got renamed, then there is already an object with this name in // the symbol table. If this happens, the old one must be a forward // decl, just replace it with a cast of the new one. if (GV->getName() != Name) { Function *F = TheModule->getFunction(Name); assert(F && F->isDeclaration() && "A function turned into a global?"); // Replace any uses of "F" with uses of GV. Value *FInNewType = ConstantExpr::getBitCast(GV, F->getType()); F->replaceAllUsesWith(FInNewType); // Update the decl that points to F. changeLLVMValue(F, FInNewType); // Now we can give GV the proper name. GV->takeName(F); // F is now dead, nuke it. F->eraseFromParent(); } } else { GV = GVE; // Global already created, reuse it. } } if ((TREE_READONLY(decl) && !TREE_SIDE_EFFECTS(decl)) || TREE_CODE(decl) == CONST_DECL) { if (DECL_EXTERNAL(decl)) { // Mark external globals constant even though they could be marked // non-constant in the defining translation unit. The definition of the // global determines whether the global is ultimately constant or not, // marking this constant will allow us to do some extra (legal) // optimizations that we would otherwise not be able to do. (In C++, // any global that is 'C++ const' may not be readonly: it could have a // dynamic initializer. // GV->setConstant(true); } else { // Mark readonly globals with constant initializers constant. if (DECL_INITIAL(decl) != error_mark_node && // uninitialized? DECL_INITIAL(decl) && (TREE_CONSTANT(DECL_INITIAL(decl)) || TREE_CODE(DECL_INITIAL(decl)) == STRING_CST)) GV->setConstant(true); } } // Set thread local (TLS) if (TREE_CODE(decl) == VAR_DECL && DECL_THREAD_LOCAL(decl)) GV->setThreadLocal(true); SET_DECL_LLVM(decl, GV); } timevar_pop(TV_LLVM_GLOBALS); } /// llvm_get_decl_name - Used by varasm.c, returns the specified declaration's /// name. const char *llvm_get_decl_name(void *LLVM) { if (LLVM == 0) return ""; return ((Value*)LLVM)->getValueName()->getKeyData(); } // llvm_mark_decl_weak - Used by varasm.c, called when a decl is found to be // weak, but it already had an llvm object created for it. This marks the LLVM // object weak as well. void llvm_mark_decl_weak(tree decl) { assert(DECL_LLVM_SET_P(decl) && DECL_WEAK(decl) && isa(DECL_LLVM(decl)) && "Decl isn't marked weak!"); GlobalValue *GV = cast(DECL_LLVM(decl)); // Do not mark something that is already known to be linkonce or internal. if (GV->hasExternalLinkage()) { if (GV->isDeclaration()) GV->setLinkage(GlobalValue::ExternalWeakLinkage); else GV->setLinkage(GlobalValue::WeakLinkage); } } // llvm_emit_ctor_dtor - Called to emit static ctors/dtors to LLVM code. fndecl // is a 'void()' FUNCTION_DECL for the code, initprio is the init priority, and // isCtor indicates whether this is a ctor or dtor. // void llvm_emit_ctor_dtor(tree FnDecl, int InitPrio, int isCtor) { mark_decl_referenced(FnDecl); // Inform cgraph that we used the global. if (errorcount || sorrycount) return; Function *F = cast_or_null(DECL_LLVM(FnDecl)); (isCtor ? &StaticCtors:&StaticDtors)->push_back(std::make_pair(F, InitPrio)); } void llvm_emit_typedef(tree decl) { // Need hooks for debug info? return; } // llvm_emit_file_scope_asm - Emit the specified string as a file-scope inline // asm block. // void llvm_emit_file_scope_asm(tree string) { if (TREE_CODE(string) == ADDR_EXPR) string = TREE_OPERAND(string, 0); if (TheModule->getModuleInlineAsm().empty()) TheModule->setModuleInlineAsm(TREE_STRING_POINTER(string)); else TheModule->setModuleInlineAsm(TheModule->getModuleInlineAsm() + "\n" + TREE_STRING_POINTER(string)); } // print_llvm - Print the specified LLVM chunk like an operand, called by // print-tree.c for tree dumps. // void print_llvm(FILE *file, void *LLVM) { oFILEstream FS(file); FS << "LLVM: "; WriteAsOperand(FS, (Value*)LLVM, true, TheModule); } // print_llvm_type - Print the specified LLVM type symbolically, called by // print-tree.c for tree dumps. // void print_llvm_type(FILE *file, void *LLVM) { oFILEstream FS(file); FS << "LLVM: "; WriteTypeSymbolic(FS, (const Type*)LLVM, TheModule); } /* APPLE LOCAL end LLVM (ENTIRE FILE!) */