From ff92a05858364cb1ae5441445e8e33a51928b730 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 31 Dec 2012 18:46:57 -0600 Subject: [PATCH] Begin to expose Pass class. --- llvm/_core.cpp | 188 +++----------------------------------------- llvm/ee.py | 75 ++---------------- llvm/extra.cpp | 26 ++++++ llvm/extra.h | 20 +++++ llvm/llvm_c_extra.h | 2 +- llvm/passes.py | 130 +++++++++++++++++++++++++++--- 6 files changed, 182 insertions(+), 259 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index fa6087a..0b53138 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -1057,97 +1057,11 @@ _wrap_none2none(LLVMInitializePTXAsmPrinter) /*===----------------------------------------------------------------------===*/ /* Passes */ /*===----------------------------------------------------------------------===*/ -/* - -#define _wrap_pass(P) \ -_wrap_obj2none( LLVMAdd ## P ## Pass, LLVMPassManagerRef) - -_wrap_pass( AAEval ) -_wrap_pass( AggressiveDCE ) -_wrap_pass( AliasAnalysisCounter ) -_wrap_pass( AlwaysInliner ) -_wrap_pass( ArgumentPromotion ) -_wrap_pass( BasicAliasAnalysis ) -_wrap_pass( BlockPlacement ) -_wrap_pass( BreakCriticalEdges ) -_wrap_pass( CFGSimplification ) -_wrap_pass( CodeGenPrepare ) -_wrap_pass( ConstantMerge ) -_wrap_pass( ConstantPropagation ) -_wrap_pass( DbgInfoPrinter ) -_wrap_pass( DeadArgElimination ) -_wrap_pass( DeadCodeElimination ) -_wrap_pass( DeadInstElimination ) -_wrap_pass( DeadStoreElimination ) -_wrap_pass( DemoteRegisterToMemory ) -_wrap_pass( DomOnlyPrinter ) -_wrap_pass( DomOnlyViewer ) -_wrap_pass( DomPrinter ) -_wrap_pass( DomViewer ) -_wrap_pass( EdgeProfiler ) -_wrap_pass( FunctionAttrs ) -_wrap_pass( FunctionInlining ) -//_wrap_pass( GEPSplitter ) -_wrap_pass( GlobalDCE ) -_wrap_pass( GlobalOptimizer ) -_wrap_pass( GlobalsModRef ) -_wrap_pass( GVN ) -_wrap_pass( IndVarSimplify ) -_wrap_pass( InstCount ) -_wrap_pass( InstructionCombining ) -_wrap_pass( InstructionNamer ) -_wrap_pass( IPConstantPropagation ) -_wrap_pass( IPSCCP ) -_wrap_pass( JumpThreading ) -_wrap_pass( LazyValueInfo ) -_wrap_pass( LCSSA ) -_wrap_pass( LICM ) -//_wrap_pass( LiveValues ) -_wrap_pass( LoopDeletion ) -_wrap_pass( LoopDependenceAnalysis ) -_wrap_pass( LoopExtractor ) -//_wrap_pass( LoopIndexSplit ) -_wrap_pass( LoopRotate ) -_wrap_pass( LoopSimplify ) -_wrap_pass( LoopStrengthReduce ) -_wrap_pass( LoopUnroll ) -_wrap_pass( LoopUnswitch ) -_wrap_pass( LowerInvoke ) -_wrap_pass( LowerSwitch ) -_wrap_pass( MemCpyOpt ) -_wrap_pass( MergeFunctions ) -_wrap_pass( NoAA ) -_wrap_pass( NoProfileInfo ) -_wrap_pass( OptimalEdgeProfiler ) -_wrap_pass( PartialInlining ) -//_wrap_pass( PartialSpecialization ) -_wrap_pass( PostDomOnlyPrinter ) -_wrap_pass( PostDomOnlyViewer ) -_wrap_pass( PostDomPrinter ) -_wrap_pass( PostDomViewer ) -_wrap_pass( ProfileEstimator ) -_wrap_pass( ProfileLoader ) -_wrap_pass( ProfileVerifier ) -_wrap_pass( PromoteMemoryToRegister ) -_wrap_pass( PruneEH ) -_wrap_pass( Reassociate ) -_wrap_pass( ScalarEvolutionAliasAnalysis ) -_wrap_pass( ScalarReplAggregates ) -_wrap_pass( SCCP ) -//_wrap_pass( SimplifyHalfPowrLibCalls ) -_wrap_pass( SimplifyLibCalls ) -_wrap_pass( SingleLoopExtractor ) -_wrap_pass( StripDeadPrototypes ) -_wrap_pass( StripNonDebugSymbols ) -_wrap_pass( StripSymbols ) -//_wrap_pass( StructRetPromotion ) -_wrap_pass( TailCallElimination ) -//_wrap_pass( TailDuplication ) -_wrap_pass( UnifyFunctionExitNodes ) - -_wrap_pass( Internalize2 ) -*/ +_wrap_str2obj(LLVMCreatePassByName, LLVMPassRef) +_wrap_obj2none(LLVMDisposePass, LLVMPassRef) +_wrap_obj2str(LLVMGetPassName, LLVMPassRef) +_wrap_objobj2none(LLVMAddPass, LLVMPassManagerRef, LLVMPassRef) /*===----------------------------------------------------------------------===*/ /* Target Machine */ @@ -2040,94 +1954,6 @@ static PyMethodDef core_methods[] = { _method( LLVMInitializePTXAsmPrinter ) # endif #endif - /* Passes */ - - /* - _pass( AAEval ) - _pass( AggressiveDCE ) - _pass( AliasAnalysisCounter ) - _pass( AlwaysInliner ) - _pass( ArgumentPromotion ) - _pass( BasicAliasAnalysis ) - _pass( BlockPlacement ) - _pass( BreakCriticalEdges ) - _pass( CFGSimplification ) - _pass( CodeGenPrepare ) - _pass( ConstantMerge ) - _pass( ConstantPropagation ) - _pass( DbgInfoPrinter ) - _pass( DeadArgElimination ) - _pass( DeadCodeElimination ) - _pass( DeadInstElimination ) - _pass( DeadStoreElimination ) - _pass( DemoteRegisterToMemory ) - _pass( DomOnlyPrinter ) - _pass( DomOnlyViewer ) - _pass( DomPrinter ) - _pass( DomViewer ) - _pass( EdgeProfiler ) - _pass( FunctionAttrs ) - _pass( FunctionInlining ) - //_pass( GEPSplitter ) - _pass( GlobalDCE ) - _pass( GlobalOptimizer ) - _pass( GlobalsModRef ) - _pass( GVN ) - _pass( IndVarSimplify ) - _pass( InstCount ) - _pass( InstructionCombining ) - _pass( InstructionNamer ) - _pass( IPConstantPropagation ) - _pass( IPSCCP ) - _pass( JumpThreading ) - _pass( LazyValueInfo ) - _pass( LCSSA ) - _pass( LICM ) - //_pass( LiveValues ) - _pass( LoopDeletion ) - _pass( LoopDependenceAnalysis ) - _pass( LoopExtractor ) - //_pass( LoopIndexSplit ) - _pass( LoopRotate ) - _pass( LoopSimplify ) - _pass( LoopStrengthReduce ) - _pass( LoopUnroll ) - _pass( LoopUnswitch ) - _pass( LowerInvoke ) - _pass( LowerSwitch ) - _pass( MemCpyOpt ) - _pass( MergeFunctions ) - _pass( NoAA ) - _pass( NoProfileInfo ) - _pass( OptimalEdgeProfiler ) - _pass( PartialInlining ) - //_pass( PartialSpecialization ) - _pass( PostDomOnlyPrinter ) - _pass( PostDomOnlyViewer ) - _pass( PostDomPrinter ) - _pass( PostDomViewer ) - _pass( ProfileEstimator ) - _pass( ProfileLoader ) - _pass( ProfileVerifier ) - _pass( PromoteMemoryToRegister ) - _pass( PruneEH ) - _pass( Reassociate ) - _pass( ScalarEvolutionAliasAnalysis ) - _pass( ScalarReplAggregates ) - _pass( SCCP ) - //_pass( SimplifyHalfPowrLibCalls ) - _pass( SimplifyLibCalls ) - _pass( SingleLoopExtractor ) - _pass( StripDeadPrototypes ) - _pass( StripNonDebugSymbols ) - _pass( StripSymbols ) - //_pass( StructRetPromotion ) - _pass( TailCallElimination ) - //_pass( TailDuplication ) - _pass( UnifyFunctionExitNodes ) - - _pass( Internalize2 ) - */ /* Target Machine */ _method( LLVMTargetMachineFromEngineBuilder ) @@ -2194,6 +2020,12 @@ static PyMethodDef core_methods[] = { _method( LLVMGenericValueToPointer ) _method( LLVMDisposeGenericValue ) + /* Passes */ + _method( LLVMCreatePassByName ) + _method( LLVMDisposePass ) + _method( LLVMGetPassName ) + _method( LLVMAddPass ) + /* Misc */ _method( LLVMGetIntrinsic ) _method( LLVMLoadLibraryPermanently ) diff --git a/llvm/ee.py b/llvm/ee.py index a23aaf4..ebe5e87 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -40,6 +40,10 @@ import logging logger = logging.getLogger(__name__) + +# re-export TargetData for backward compatibility. +from llvm.passes import TargetData + #===----------------------------------------------------------------------=== # Enumerations #===----------------------------------------------------------------------=== @@ -48,76 +52,6 @@ BO_BIG_ENDIAN = 0 BO_LITTLE_ENDIAN = 1 -#===----------------------------------------------------------------------=== -# Target data -#===----------------------------------------------------------------------=== - -class TargetData(llvm.Ownable): - - @staticmethod - def new(strrep): - return TargetData(_core.LLVMCreateTargetData(strrep)) - - def __init__(self, ptr): - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetData) - - def __str__(self): - return _core.LLVMTargetDataAsString(self.ptr) - - @property - def byte_order(self): - return _core.LLVMByteOrder(self.ptr) - - @property - def pointer_size(self): - return _core.LLVMPointerSize(self.ptr) - - @property - def target_integer_type(self): - ptr = _core.LLVMIntPtrType(self.ptr); - return core.IntegerType(ptr, core.TYPE_INTEGER) - - def size(self, ty): - core.check_is_type(ty) - return _core.LLVMSizeOfTypeInBits(self.ptr, ty.ptr) - - def store_size(self, ty): - core.check_is_type(ty) - return _core.LLVMStoreSizeOfType(self.ptr, ty.ptr) - - def abi_size(self, ty): - core.check_is_type(ty) - return _core.LLVMABISizeOfType(self.ptr, ty.ptr) - - def abi_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMABIAlignmentOfType(self.ptr, ty.ptr) - - def callframe_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMCallFrameAlignmentOfType(self.ptr, ty.ptr) - - def preferred_alignment(self, ty_or_gv): - if isinstance(ty_or_gv, core.Type): - return _core.LLVMPreferredAlignmentOfType(self.ptr, - ty_or_gv.ptr) - elif isinstance(ty_or_gv, core.GlobalVariable): - return _core.LLVMPreferredAlignmentOfGlobal(self.ptr, - ty_or_gv.ptr) - else: - raise core.LLVMException("argument is neither a type nor a global variable") - - def element_at_offset(self, ty, ofs): - core.check_is_type_struct(ty) - ofs = int(ofs) # ofs is unsigned long long - return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs) - - def offset_of_element(self, ty, el): - core.check_is_type_struct(ty) - el = int(el) # el should be an int - return _core.LLVMOffsetOfElement(self.ptr, ty.ptr, el) - - #===----------------------------------------------------------------------=== # Generic value #===----------------------------------------------------------------------=== @@ -383,3 +317,4 @@ class TargetMachine(object): @property def feature_string(self): return _core.LLVMTargetMachineGetFS(self.ptr) + diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 484f9ac..e58220d 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -95,6 +95,7 @@ namespace llvm{ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(NamedMDNode, LLVMNamedMDRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) template inline T **unwrap(LLVMTypeRef *Tys, unsigned Length) { @@ -143,6 +144,31 @@ const CodeGenOpt::Level OptLevelMap[] = { } // end anony namespace +LLVMPassRef LLVMCreatePassByName(const char *name){ + using namespace llvm; + const PassInfo * pi = Pass::lookupPassInfo(StringRef(name)); + if (pi) { + return wrap(pi->createPass()); + } else { // cannot find pass + return NULL; + } +} + +void LLVMDisposePass(LLVMPassRef passref){ + using namespace llvm; + delete unwrap(passref); +} + +const char * LLVMGetPassName(LLVMPassRef passref){ + using namespace llvm; + return unwrap(passref)->getPassName(); +} + +void LLVMAddPass(LLVMPassManagerRef pmref, LLVMPassRef passref){ + using namespace llvm; + unwrap(pmref)->add(unwrap(passref)); +} + LLVMValueRef LLVMGetFunctionFromInlineAsm(LLVMTypeRef funcType, const char inlineAsm[], const char constrains[], diff --git a/llvm/extra.h b/llvm/extra.h index 97cc31b..49a75d1 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -54,6 +54,26 @@ extern "C" { #endif +/* + * Wraps Pass::lookupPassInfo and PassInfo::createPass + */ +LLVMPassRef LLVMCreatePassByName(const char *name); + +/* + * Wraps operator delete (Pass*) + */ +void LLVMDisposePass(LLVMPassRef passref); + +/* + * Wraps Pass::getPassName + */ +const char * LLVMGetPassName(LLVMPassRef passref); + +/* + * Wraps PassManager::add + */ +void LLVMAddPass(LLVMPassManagerRef pmref, LLVMPassRef passref); + /* * Wraps llvm:InlineAsm::get */ diff --git a/llvm/llvm_c_extra.h b/llvm/llvm_c_extra.h index 9eb77dc..5728875 100644 --- a/llvm/llvm_c_extra.h +++ b/llvm/llvm_c_extra.h @@ -21,7 +21,7 @@ inline ref wrap(const ty *P) { \ typedef struct LLVMOpaqueEngineBuilder *LLVMEngineBuilderRef; typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; typedef struct LLVMOpaqueNamedMD *LLVMNamedMDRef; - +typedef struct LLVMOpaquePass *LLVMPassRef; #ifdef __cplusplus } diff --git a/llvm/passes.py b/llvm/passes.py index d06fa59..71de28d 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -36,7 +36,6 @@ are available. """ import llvm # top-level, for common stuff -import llvm.ee as ee # target data import llvm.core as core # module, function etc. import llvm._core as _core # C wrappers import llvm._util as _util # Utility functions @@ -155,16 +154,18 @@ class PassManager(object): def __del__(self): _core.LLVMDisposePassManager(self.ptr) - def add(self, tgt_data_or_pass_name): - if isinstance(tgt_data_or_pass_name, ee.TargetData): - self._add_target_data(tgt_data_or_pass_name) - elif _util.isstring(tgt_data_or_pass_name): - self._add_pass(tgt_data_or_pass_name) + def add(self, pass_obj): + '''Add a pass to the pass manager. + + pass_obj --- Either a Pass instance, a string name of a pass + ''' + if isinstance(pass_obj, Pass): + _core.LLVMAddPass(self.ptr, pass_obj.ptr) + pass_obj._own(self) # PassManager owns the pass + elif _util.isstring(pass_obj): + self._add_pass(pass_obj) else: - raise llvm.LLVMException("invalid pass_id (%s)" % tgt_data_or_pass_name) - - def _add_target_data(self, tgt): - _core.LLVMAddTargetData(tgt.ptr, self.ptr) + raise llvm.LLVMException("invalid pass_id (%s)" % pass_obj) def _add_pass(self, pass_name): status = _core.LLVMAddPassByName(self.ptr, pass_name) @@ -197,6 +198,115 @@ class FunctionPassManager(PassManager): def finalize(self): _core.LLVMFinalizeFunctionPassManager(self.ptr) + + +#===----------------------------------------------------------------------=== +# Passes +#===----------------------------------------------------------------------=== + +class Pass(llvm.Ownable): + '''Pass Inferface + ''' + def __init__(self, ptr): + llvm.Ownable.__init__(self, ptr, _core.LLVMDisposePass) + + @staticmethod + def new(name): + '''Create a new pass by name. + + Note: Not all pass has a default constructor. LLVM will kill + the process if an the pass requires arguments to construct. + The error cannot be caught. + ''' + ptr = _core.LLVMCreatePassByName(name) + p = Pass(ptr) + p.__name = name + return p + + @property + def name(self): + return self.__name + + @property + def description(self): + return _core.LLVMGetPassName(self.ptr) + + def dump(self): + return _core.LLVMPassDump(self.ptr) + + +#===----------------------------------------------------------------------=== +# Target data +#===----------------------------------------------------------------------=== + +class TargetData(Pass): + + @staticmethod + def new(strrep): + return TargetData(_core.LLVMCreateTargetData(strrep)) + + def __str__(self): + return _core.LLVMTargetDataAsString(self.ptr) + + @property + def byte_order(self): + return _core.LLVMByteOrder(self.ptr) + + @property + def pointer_size(self): + return _core.LLVMPointerSize(self.ptr) + + @property + def target_integer_type(self): + ptr = _core.LLVMIntPtrType(self.ptr); + return core.IntegerType(ptr, core.TYPE_INTEGER) + + def size(self, ty): + core.check_is_type(ty) + return _core.LLVMSizeOfTypeInBits(self.ptr, ty.ptr) + + def store_size(self, ty): + core.check_is_type(ty) + return _core.LLVMStoreSizeOfType(self.ptr, ty.ptr) + + def abi_size(self, ty): + core.check_is_type(ty) + return _core.LLVMABISizeOfType(self.ptr, ty.ptr) + + def abi_alignment(self, ty): + core.check_is_type(ty) + return _core.LLVMABIAlignmentOfType(self.ptr, ty.ptr) + + def callframe_alignment(self, ty): + core.check_is_type(ty) + return _core.LLVMCallFrameAlignmentOfType(self.ptr, ty.ptr) + + def preferred_alignment(self, ty_or_gv): + if isinstance(ty_or_gv, core.Type): + return _core.LLVMPreferredAlignmentOfType(self.ptr, + ty_or_gv.ptr) + elif isinstance(ty_or_gv, core.GlobalVariable): + return _core.LLVMPreferredAlignmentOfGlobal(self.ptr, + ty_or_gv.ptr) + else: + raise core.LLVMException("argument is neither a type nor a global variable") + + def element_at_offset(self, ty, ofs): + core.check_is_type_struct(ty) + ofs = int(ofs) # ofs is unsigned long long + return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs) + + def offset_of_element(self, ty, el): + core.check_is_type_struct(ty) + el = int(el) # el should be an int + return _core.LLVMOffsetOfElement(self.ptr, ty.ptr, el) + + + +#===----------------------------------------------------------------------=== +# Misc. +#===----------------------------------------------------------------------=== + # Intialize passes PASSES = None