mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	several things that were neither in an anonymous namespace nor static but not intended to be global. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51017 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			172 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- OcamlCollector.cpp - Ocaml frametable emitter ---------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements lowering for the llvm.gc* intrinsics compatible with
 | |
| // Objective Caml 3.10.0, which uses a liveness-accurate static stack map.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
|                         
 | |
| #include "llvm/CodeGen/Collectors.h"
 | |
| #include "llvm/CodeGen/AsmPrinter.h"
 | |
| #include "llvm/CodeGen/Collector.h"
 | |
| #include "llvm/Module.h"
 | |
| #include "llvm/Target/TargetAsmInfo.h"
 | |
| #include "llvm/Target/TargetData.h"
 | |
| #include "llvm/Target/TargetMachine.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
|   class VISIBILITY_HIDDEN OcamlCollector : public Collector {
 | |
|   public:
 | |
|     OcamlCollector();
 | |
|     
 | |
|     void beginAssembly(std::ostream &OS, AsmPrinter &AP,
 | |
|                        const TargetAsmInfo &TAI);
 | |
|     
 | |
|     void finishAssembly(std::ostream &OS, AsmPrinter &AP,
 | |
|                         const TargetAsmInfo &TAI);
 | |
|   };
 | |
|   
 | |
| }
 | |
| 
 | |
| static CollectorRegistry::Add<OcamlCollector>
 | |
| X("ocaml", "ocaml 3.10-compatible collector");
 | |
| 
 | |
| // -----------------------------------------------------------------------------
 | |
| 
 | |
| static void EmitCamlGlobal(const Module &M, std::ostream &OS, AsmPrinter &AP,
 | |
|                            const TargetAsmInfo &TAI, const char *Id) {
 | |
|   const std::string &MId = M.getModuleIdentifier();
 | |
|   
 | |
|   std::string Mangled;
 | |
|   Mangled += TAI.getGlobalPrefix();
 | |
|   Mangled += "caml";
 | |
|   size_t Letter = Mangled.size();
 | |
|   Mangled.append(MId.begin(), std::find(MId.begin(), MId.end(), '.'));
 | |
|   Mangled += "__";
 | |
|   Mangled += Id;
 | |
|   
 | |
|   // Capitalize the first letter of the module name.
 | |
|   Mangled[Letter] = toupper(Mangled[Letter]);
 | |
|   
 | |
|   if (const char *GlobalDirective = TAI.getGlobalDirective())
 | |
|     OS << GlobalDirective << Mangled << "\n";
 | |
|   OS << Mangled << ":\n";
 | |
| }
 | |
| 
 | |
| Collector *llvm::createOcamlCollector() {
 | |
|   return new OcamlCollector();
 | |
| }
 | |
| 
 | |
| OcamlCollector::OcamlCollector() {
 | |
|   NeededSafePoints = 1 << GC::PostCall;
 | |
| }
 | |
| 
 | |
| void OcamlCollector::beginAssembly(std::ostream &OS, AsmPrinter &AP,
 | |
|                                    const TargetAsmInfo &TAI) {
 | |
|   AP.SwitchToTextSection(TAI.getTextSection());
 | |
|   EmitCamlGlobal(getModule(), OS, AP, TAI, "code_begin");
 | |
|   
 | |
|   AP.SwitchToDataSection(TAI.getDataSection());
 | |
|   EmitCamlGlobal(getModule(), OS, AP, TAI, "data_begin");
 | |
| }
 | |
| 
 | |
| /// emitAssembly - Print the frametable. The ocaml frametable format is thus:
 | |
| /// 
 | |
| ///   extern "C" struct align(sizeof(intptr_t)) {
 | |
| ///     uint16_t NumDescriptors;
 | |
| ///     struct align(sizeof(intptr_t)) {
 | |
| ///       void *ReturnAddress;
 | |
| ///       uint16_t FrameSize;
 | |
| ///       uint16_t NumLiveOffsets;
 | |
| ///       uint16_t LiveOffsets[NumLiveOffsets];
 | |
| ///     } Descriptors[NumDescriptors];
 | |
| ///   } caml${module}__frametable;
 | |
| /// 
 | |
| /// Note that this precludes programs from stack frames larger than 64K
 | |
| /// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if
 | |
| /// either condition is detected in a function which uses the collector.
 | |
| /// 
 | |
| void OcamlCollector::finishAssembly(std::ostream &OS, AsmPrinter &AP,
 | |
|                                     const TargetAsmInfo &TAI) {
 | |
|   const char *AddressDirective;
 | |
|   int AddressAlignLog;
 | |
|   if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) {
 | |
|     AddressDirective = TAI.getData32bitsDirective();
 | |
|     AddressAlignLog = 2;
 | |
|   } else {
 | |
|     AddressDirective = TAI.getData64bitsDirective();
 | |
|     AddressAlignLog = 3;
 | |
|   }
 | |
| 
 | |
|   AP.SwitchToTextSection(TAI.getTextSection());
 | |
|   EmitCamlGlobal(getModule(), OS, AP, TAI, "code_end");
 | |
|   
 | |
|   AP.SwitchToDataSection(TAI.getDataSection());
 | |
|   EmitCamlGlobal(getModule(), OS, AP, TAI, "data_end");
 | |
|   
 | |
|   OS << AddressDirective << 0; // FIXME: Why does ocaml emit this??
 | |
|   AP.EOL();
 | |
|   
 | |
|   AP.SwitchToDataSection(TAI.getDataSection());
 | |
|   EmitCamlGlobal(getModule(), OS, AP, TAI, "frametable");
 | |
|   
 | |
|   for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
 | |
|     CollectorMetadata &MD = **FI;
 | |
|     
 | |
|     OS << "\t" << TAI.getCommentString() << " live roots for "
 | |
|        << MD.getFunction().getNameStart() << "\n";
 | |
|     
 | |
|     for (CollectorMetadata::iterator PI = MD.begin(),
 | |
|                                      PE = MD.end(); PI != PE; ++PI) {
 | |
|       
 | |
|       uint64_t FrameSize = MD.getFrameSize();
 | |
|       if (FrameSize >= 2<<16) {
 | |
|         cerr << "Function '" << MD.getFunction().getNameStart()
 | |
|              << "' is too large for the ocaml collector! "
 | |
|              << "Frame size " << FrameSize << " >= 65536.\n";
 | |
|         abort(); // Very rude!
 | |
|       }
 | |
|       
 | |
|       size_t LiveCount = MD.live_size(PI);
 | |
|       if (LiveCount >= 2<<16) {
 | |
|         cerr << "Function '" << MD.getFunction().getNameStart()
 | |
|              << "' is too large for the ocaml collector! "
 | |
|              << "Live root count " << LiveCount << " >= 65536.\n";
 | |
|         abort(); // Very rude!
 | |
|       }
 | |
|       
 | |
|       OS << AddressDirective
 | |
|          << TAI.getPrivateGlobalPrefix() << "label" << PI->Num;
 | |
|       AP.EOL("call return address");
 | |
|       
 | |
|       AP.EmitInt16(FrameSize);
 | |
|       AP.EOL("stack frame size");
 | |
|       
 | |
|       AP.EmitInt16(LiveCount);
 | |
|       AP.EOL("live root count");
 | |
|       
 | |
|       for (CollectorMetadata::live_iterator LI = MD.live_begin(PI),
 | |
|                                             LE = MD.live_end(PI);
 | |
|                                             LI != LE; ++LI) {
 | |
|         assert(LI->StackOffset < 2<<16 &&
 | |
|                "GC root stack offset is outside of fixed stack frame and out "
 | |
|                "of range for Ocaml collector!");
 | |
|         
 | |
|         OS << "\t.word\t" << LI->StackOffset;
 | |
|         AP.EOL("stack offset");
 | |
|       }
 | |
|       
 | |
|       AP.EmitAlignment(AddressAlignLog);
 | |
|     }
 | |
|   }
 | |
| }
 |