├── .classpath ├── .cproject ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── AUTHORS ├── Makefile ├── README ├── build.xml ├── config.mak.example ├── include └── liboo │ ├── ddispatch.h │ ├── debuginfo.h │ ├── dmemory.h │ ├── eh.h │ ├── oo.h │ ├── opt.h │ ├── rta.h │ ├── rts_types.h │ └── rtti.h ├── spec ├── config.example ├── generate_headerbindings.sh ├── javagen.sh ├── javaspec.py └── oo_nodes_spec.py ├── src-cpp ├── adt │ ├── align.h │ ├── array.h │ ├── bitfiddle.h │ ├── compiler.h │ ├── cpmap.c │ ├── cpmap.h │ ├── cpset.c │ ├── cpset.h │ ├── error.h │ ├── fourcc.h │ ├── hashptr.h │ ├── hashset.c.h │ ├── hashset.h │ ├── obst.h │ ├── obstack.c │ ├── obstack.h │ ├── obstack_printf.c │ ├── pdeq.c │ ├── pdeq.h │ ├── pdeq.o │ ├── raw_bitset.h │ ├── util.h │ └── xmalloc.h ├── ddispatch.c ├── debuginfo.c ├── dmemory.c ├── eh.c ├── nodes_attr.h ├── oo.c ├── opt.c ├── rt │ ├── error_functions.c │ ├── exceptions.c │ ├── instanceof.c │ ├── interface_lookup.c │ ├── rt.h │ └── types.h ├── rta.c └── rtti.c └── src └── firm ├── DebugInfo.java ├── OO.java ├── RTA.java ├── bindings ├── binding_nodes.java ├── binding_oo.java └── binding_rta.java └── oo └── nodes ├── Arraylength.java ├── InstanceOf.java ├── MethodSel.java ├── Nodes.java └── VptrIsSet.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /classes 3 | /lib 4 | /config.mak 5 | /spec/config 6 | /include/liboo/nodes.h 7 | /src-cpp/gen_irnode.c 8 | /src-cpp/gen_irnode.h 9 | *.pyc 10 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | liboo 4 | 5 | 6 | jFirm 7 | libfirm 8 | 9 | 10 | 11 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 12 | clean,full,incremental, 13 | 14 | 15 | ?name? 16 | 17 | 18 | 19 | org.eclipse.cdt.make.core.append_environment 20 | true 21 | 22 | 23 | org.eclipse.cdt.make.core.autoBuildTarget 24 | all 25 | 26 | 27 | org.eclipse.cdt.make.core.buildArguments 28 | 29 | 30 | 31 | org.eclipse.cdt.make.core.buildCommand 32 | make 33 | 34 | 35 | org.eclipse.cdt.make.core.cleanBuildTarget 36 | clean 37 | 38 | 39 | org.eclipse.cdt.make.core.contents 40 | org.eclipse.cdt.make.core.activeConfigSettings 41 | 42 | 43 | org.eclipse.cdt.make.core.enableAutoBuild 44 | false 45 | 46 | 47 | org.eclipse.cdt.make.core.enableCleanBuild 48 | true 49 | 50 | 51 | org.eclipse.cdt.make.core.enableFullBuild 52 | true 53 | 54 | 55 | org.eclipse.cdt.make.core.fullBuildTarget 56 | all 57 | 58 | 59 | org.eclipse.cdt.make.core.stopOnError 60 | true 61 | 62 | 63 | org.eclipse.cdt.make.core.useDefaultBuildCmd 64 | true 65 | 66 | 67 | 68 | 69 | org.eclipse.jdt.core.javabuilder 70 | 71 | 72 | 73 | 74 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 75 | full,incremental, 76 | 77 | 78 | 79 | 80 | 81 | org.eclipse.jdt.core.javanature 82 | org.eclipse.cdt.core.cnature 83 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 84 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 85 | 86 | 87 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Fri Dec 03 12:47:22 CET 2010 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning 4 | org.eclipse.jdt.core.compiler.problem.autoboxing=warning 5 | org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning 6 | org.eclipse.jdt.core.compiler.problem.deadCode=warning 7 | org.eclipse.jdt.core.compiler.problem.deprecation=warning 8 | org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled 9 | org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled 10 | org.eclipse.jdt.core.compiler.problem.discouragedReference=warning 11 | org.eclipse.jdt.core.compiler.problem.emptyStatement=warning 12 | org.eclipse.jdt.core.compiler.problem.fallthroughCase=error 13 | org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled 14 | org.eclipse.jdt.core.compiler.problem.fieldHiding=warning 15 | org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning 16 | org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error 17 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=error 18 | org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning 19 | org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning 20 | org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning 21 | org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning 22 | org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning 23 | org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning 24 | org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning 25 | org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning 26 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning 27 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled 28 | org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore 29 | org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning 30 | org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning 31 | org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning 32 | org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore 33 | org.eclipse.jdt.core.compiler.problem.nullReference=error 34 | org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning 35 | org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning 36 | org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error 37 | org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning 38 | org.eclipse.jdt.core.compiler.problem.rawTypeReference=error 39 | org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning 40 | org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning 41 | org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled 42 | org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning 43 | org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled 44 | org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled 45 | org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning 46 | org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning 47 | org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning 48 | org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore 49 | org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning 50 | org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning 51 | org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning 52 | org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore 53 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning 54 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled 55 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled 56 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled 57 | org.eclipse.jdt.core.compiler.problem.unusedImport=warning 58 | org.eclipse.jdt.core.compiler.problem.unusedLabel=warning 59 | org.eclipse.jdt.core.compiler.problem.unusedLocal=warning 60 | org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning 61 | org.eclipse.jdt.core.compiler.problem.unusedParameter=warning 62 | org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled 63 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled 64 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled 65 | org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error 66 | org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning 67 | org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning 68 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Julian Oppermann 2 | Matthias Braun 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | variant ?= debug 2 | 3 | -include config.mak 4 | 5 | FIRM_HOME ?= ../libfirm 6 | LIBFIRM_CPPFLAGS ?= -I$(FIRM_HOME)/include -I$(FIRM_HOME)/build/gen/include/libfirm 7 | LIBFIRM_LFLAGS ?= -L$(FIRM_HOME)/build/$(variant) -lfirm 8 | INSTALL ?= install 9 | DLLEXT ?= .so 10 | CC ?= gcc 11 | AR ?= ar 12 | CFLAGS ?= -O0 -g3 13 | 14 | guessed_target := $(shell $(CC) -dumpmachine) 15 | TARGET ?= $(guessed_target) 16 | TARGET_CC ?= $(TARGET)-gcc 17 | 18 | ifeq ($(findstring darwin11, $(TARGET)), darwin11) 19 | # compile library normally but runtime in 32bit mode 20 | RT_CFLAGS += -m32 21 | RT_LFLAGS += -m32 22 | endif 23 | ifeq ($(findstring x86_64, $(guessed_target)), x86_64) 24 | ifeq ($(findstring i686, $(TARGET)), i686) 25 | # compile library normally but runtime in 32bit mode 26 | RT_CFLAGS += -m32 27 | RT_LFLAGS += -m32 28 | endif 29 | endif 30 | ifeq ($(findstring i686-invasic, $(TARGET)), i686-invasic) 31 | OCTOPOS_BASE=../octopos-app/releases/current/x86guest/default 32 | GCC_INCLUDE:=$(shell $(TARGET_CC) --print-file-name=include) 33 | RT_CFLAGS += -m32 -fno-stack-protector -mfpmath=sse -msse2 -nostdinc -isystem $(GCC_INCLUDE) -I $(OCTOPOS_BASE)/include -ffreestanding 34 | RT_LFLAGS += -m32 -nostdlib -Wl,-T,$(OCTOPOS_BASE)/lib/sections.x $(OCTOPOS_BASE)/lib/libcsubset.a $(OCTOPOS_BASE)/lib/liboctopos.a 35 | endif 36 | ifeq ($(findstring x86_64-invasic, $(TARGET)), x86_64-invasic) 37 | OCTOPOS_BASE=../octopos-app/releases/current/x64native/default 38 | GCC_INCLUDE:=$(shell $(TARGET_CC) --print-file-name=include) 39 | RT_CFLAGS += -mno-red-zone -nostdinc -isystem $(GCC_INCLUDE) -I $(OCTOPOS_BASE)/include -ffreestanding 40 | RT_LFLAGS += -nostdlib -Wl,-T,$(OCTOPOS_BASE)/lib/sections.x $(OCTOPOS_BASE)/lib/libcsubset.a $(OCTOPOS_BASE)/lib/liboctopos.a 41 | endif 42 | ifeq ($(findstring sparc-invasic, $(TARGET)), sparc-invasic) 43 | OCTOPOS_BASE=../octopos-app/releases/current/leon/default 44 | GCC_INCLUDE:=$(shell $(TARGET_CC) --print-file-name=include) 45 | RT_CFLAGS += -fno-stack-protector -nostdinc -I $(OCTOPOS_BASE)/include -isystem $(GCC_INCLUDE) -ffreestanding 46 | RT_LFLAGS += -nostdlib -Wl,-T,$(OCTOPOS_BASE)/lib/sections.x $(OCTOPOS_BASE)/lib/libcsubset.a $(OCTOPOS_BASE)/lib/liboctopos.a 47 | endif 48 | 49 | BUILDDIR=build 50 | RUNTIME_BUILDDIR=$(BUILDDIR)/$(TARGET) 51 | GOAL = $(BUILDDIR)/liboo$(DLLEXT) 52 | GOAL_STATIC = $(BUILDDIR)/liboo.a 53 | GOAL_RT_SHARED = $(RUNTIME_BUILDDIR)/liboo_rt$(DLLEXT) 54 | GOAL_RT_STATIC = $(RUNTIME_BUILDDIR)/liboo_rt.a 55 | # We only need a static runtime lib for invasic targets 56 | ifeq ($(findstring invasic, $(TARGET)), invasic) 57 | GOAL_RT_SHARED = 58 | endif 59 | CPPFLAGS = -I. -I./include/ $(LIBFIRM_CPPFLAGS) $(LIBUNWIND_CPPFLAGS) 60 | CFLAGS += -Wall -W -Wstrict-prototypes -Wmissing-prototypes -std=c99 -pedantic 61 | # disabled the following warnings for now. They fail on OS/X Snow Leopard: 62 | # the first one gives false positives because of system headers, the later one 63 | # doesn't exist in the old gcc there 64 | #CFLAGS += -Wunreachable-code -Wlogical-op 65 | LFLAGS += 66 | PIC_FLAGS = -fpic 67 | SOURCES = $(wildcard src-cpp/*.c) $(wildcard src-cpp/adt/*.c) 68 | SOURCES_RT = $(wildcard src-cpp/rt/*.c) 69 | SOURCES := $(filter-out src-cpp/gen_%.c, $(SOURCES)) src-cpp/gen_irnode.c 70 | OBJECTS = $(addprefix $(BUILDDIR)/, $(addsuffix .o, $(basename $(SOURCES)))) 71 | OBJECTS_RT_SHARED = $(addprefix $(RUNTIME_BUILDDIR)/shared/, $(addsuffix .o, $(basename $(SOURCES_RT)))) 72 | OBJECTS_RT_STATIC = $(addprefix $(RUNTIME_BUILDDIR)/static/, $(addsuffix .o, $(basename $(SOURCES_RT)))) 73 | DEPS = $(OBJECTS:%.o=%.d) $(OBJECTS_RT_SHARED:%.o=%.d) $(OBJECTS_RT_STATIC:%.o=%.d) 74 | 75 | Q ?= @ 76 | 77 | .PHONY: all runtime clean 78 | 79 | all: $(GOAL) $(GOAL_STATIC) runtime 80 | 81 | runtime: $(GOAL_RT_SHARED) $(GOAL_RT_STATIC) 82 | 83 | # Make sure our build-directories are created 84 | UNUSED := $(shell mkdir -p $(BUILDDIR)/src-cpp/rt $(BUILDDIR)/src-cpp/adt $(RUNTIME_BUILDDIR)/shared/src-cpp/rt $(RUNTIME_BUILDDIR)/static/src-cpp/rt) 85 | 86 | -include $(DEPS) 87 | 88 | SPEC_GENERATED_HEADERS := include/liboo/nodes.h src-cpp/gen_irnode.h 89 | SPECGENDIR := $(FIRM_HOME)/scripts 90 | IR_SPEC_GENERATOR := $(SPECGENDIR)/gen_ir.py 91 | IR_SPEC_GENERATOR_DEPS := $(IR_SPEC_GENERATOR) $(SPECGENDIR)/irops.py $(SPECGENDIR)/filters.py $(SPECGENDIR)/jinjautil.py 92 | SPECFILE := spec/oo_nodes_spec.py 93 | 94 | $(SOURCES): $(SPEC_GENERATED_HEADERS) 95 | 96 | include/liboo/% : $(FIRM_HOME)/scripts/templates/% $(IR_SPEC_GENERATOR_DEPS) $(SPECFILE) 97 | @echo GEN $@ 98 | $(Q)$(IR_SPEC_GENERATOR) "$(SPECFILE)" "$<" > "$@" 99 | 100 | src-cpp/% : $(FIRM_HOME)/scripts/templates/% $(IR_SPEC_GENERATOR_DEPS) $(SPECFILE) 101 | @echo GEN $@ 102 | $(Q)$(IR_SPEC_GENERATOR) "$(SPECFILE)" "$<" > "$@" 103 | 104 | $(GOAL): $(OBJECTS) 105 | @echo '===> LD $@' 106 | $(Q)$(CC) -shared -o $@ $^ $(LFLAGS) $(LIBFIRM_LFLAGS) 107 | 108 | $(GOAL_STATIC): $(OBJECTS) 109 | @echo '===> AR $@' 110 | $(Q)$(AR) -cr $@ $^ 111 | 112 | $(GOAL_RT_SHARED): $(OBJECTS_RT_SHARED) 113 | @echo '===> LD $@' 114 | $(Q)$(TARGET_CC) -shared $(RT_LFLAGS) $(PIC_FLAGS) -o $@ $^ $(LFLAGS) $(LIBUNWIND_LFLAGS) 115 | 116 | $(GOAL_RT_STATIC): $(OBJECTS_RT_STATIC) 117 | @echo '===> AR $@' 118 | $(Q)$(AR) -cr $@ $^ 119 | 120 | $(RUNTIME_BUILDDIR)/shared/%.o: %.c 121 | @echo '===> TARGET_CC $@' 122 | $(Q)$(TARGET_CC) $(CPPFLAGS) $(CFLAGS) $(RT_CFLAGS) $(PIC_FLAGS) -MP -MMD -c -o $@ $< 123 | 124 | $(RUNTIME_BUILDDIR)/static/%.o: %.c 125 | @echo '===> TARGET_CC $@' 126 | $(Q)$(TARGET_CC) $(CPPFLAGS) $(CFLAGS) $(RT_CFLAGS) -MP -MMD -c -o $@ $< 127 | 128 | $(BUILDDIR)/%.o: %.c 129 | @echo '===> CC $@' 130 | $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) $(PIC_FLAGS) -MP -MMD -c -o $@ $< 131 | 132 | clean: 133 | rm -rf $(OBJECTS) $(OBJECTS_RT_SHARED) $(OBJECTS_RT_STATIC) $(GOAL) $(GOAL_RT_STATIC) $(GOAL_RT_SHARED) $(DEPS) $(DEPS_RT) $(RUNTIME_BUILDDIR) $(SPEC_GENERATED_HEADERS) 134 | 135 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This library provides support for compilation of object-oriented constructs in firm. Since firm mostly deals with low-level things you need an additional layer to produce things like vtable or name-mangling. This library provides them. 2 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | firm object-orientation support library 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | FIRM_HOME = ../libfirm 35 | LIBFIRM_CPPFLAGS = -I$(FIRM_HOME)/include -I$(FIRM_HOME)/build/gen/include/libfirm 36 | LIBFIRM_LFLAGS = -L$(FIRM_HOME)/build/$(variant) -lfirm 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /config.mak.example: -------------------------------------------------------------------------------- 1 | FIRM_HOME = ../libfirm 2 | LIBFIRM_CPPFLAGS = -I$(FIRM_HOME)/include -I$(FIRM_HOME)/build/gen/include/libfirm 3 | LIBFIRM_LFLAGS = -L$(FIRM_HOME)/build/debug -lfirm 4 | -------------------------------------------------------------------------------- /include/liboo/ddispatch.h: -------------------------------------------------------------------------------- 1 | #ifndef OO_DDISPATCH_H 2 | #define OO_DDISPATCH_H 3 | 4 | /* 5 | * Layout of the created dynamic dispatch table (vtable): 6 | * 7 | * Default layout: 8 | * 9 | * _ZTVNxyzE: 10 | * runtime classinfo 11 | * addr(first method) 12 | * ... 13 | * addr(last method) 14 | * 15 | * More complicated layouts are possible, use ddispatch_set_vtable_layout(..). 16 | * The resulting vtable will look like this: 17 | * 18 | * _ZTVNxyzE: 19 | * 0 uninitialized* 20 | * 0 uninitialized* 21 | * runtime classinfo <-- vtable_vptr_points_to_index (e.g., == 2) 22 | * uninitialized* 23 | * addr(first method) <-- vtable_index_of_first_method (e.g., == 4) 24 | * ... 25 | * addr(last method) 26 | * 27 | * *) use callback function vtable_init_slots to set ir_initializer_t's 28 | * for the uninitialized slots. 29 | */ 30 | 31 | #include 32 | 33 | /* 34 | * This property specifies how a 35 | * 36 | * class method entity 37 | * \ / 38 | * Sel 39 | * | 40 | * Call 41 | * 42 | * construction should be lowered. 43 | * 44 | * bind_static : no further indirection should be performed, just call the specified method. 45 | * bind_dynamic : use the vtable mechanism to determine the real callee. 46 | * bind_interface: invoke a special lookup method at runtime to get the callee. 47 | * 48 | * NOTE: This does not distinguish class/static vs. instance methods or fields. 49 | * 50 | */ 51 | typedef enum { 52 | bind_unknown, 53 | bind_static, 54 | bind_dynamic, 55 | bind_interface 56 | } ddispatch_binding; 57 | 58 | typedef enum { 59 | call_runtime_lookup = 0, 60 | call_searched_itable = 1, 61 | call_itable_indexed = 2, 62 | call_move2front = 4 63 | } ddispatch_interface_call; 64 | 65 | 66 | typedef void (*init_vtable_slots_t) (ir_type* klass, ir_initializer_t *vtable_init, unsigned vtable_size); 67 | typedef ir_node* (*construct_interface_lookup_t) (ir_node *objptr, ir_type *iface, ir_entity *method, ir_graph *irg, ir_node *block, ir_node **mem); 68 | 69 | void ddispatch_init(void); 70 | void ddispatch_deinit(void); 71 | void ddispatch_setup_vtable(ir_type *klass); 72 | void ddispatch_lower_Call(ir_node* call); 73 | void ddispatch_prepare_new_instance(dbg_info *dbgi, ir_node *block, ir_node *objptr, ir_node **mem, ir_type* klass); 74 | 75 | void ddispatch_setup_itable(ir_type *klass); 76 | int ddispatch_get_itable_method_index(ir_type *interface, ir_entity *method); 77 | ir_entity *ddispatch_get_itable_id(ir_type *interface); 78 | unsigned ddispatch_get_itable_index(ir_type *interface); 79 | ir_type *ddispatch_get_itt_entry_type(void); 80 | 81 | 82 | void ddispatch_set_vtable_layout(unsigned vptr_points_to_index, unsigned index_of_first_method, unsigned index_of_rtti_ptr, init_vtable_slots_t func); 83 | void ddispatch_set_interface_lookup_constructor(construct_interface_lookup_t func); 84 | void ddispatch_set_abstract_method_entity(ir_entity *method); 85 | 86 | unsigned ddispatch_get_vptr_points_to_index(void); 87 | unsigned ddispatch_get_index_of_rtti_ptr(void); 88 | unsigned ddispatch_get_index_of_first_method(void); 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /include/liboo/debuginfo.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUGINFO_H 2 | #define DEBUGINFO_H 3 | 4 | #include 5 | 6 | void debuginfo_init(void); 7 | const dbg_info *create_debuginfo(ident *filename, unsigned linenr, 8 | unsigned column, unsigned length); 9 | void debuginfo_deinit(void); 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /include/liboo/dmemory.h: -------------------------------------------------------------------------------- 1 | #ifndef OO_DMEMORY_H 2 | #define OO_DMEMORY_H 3 | 4 | #include 5 | 6 | typedef ir_node* (*get_arraylength_t) (dbg_info *dbgi, ir_node *block, ir_node *objptr, ir_node **mem); 7 | 8 | ir_node *dmemory_default_get_arraylength(dbg_info *dbgi, ir_node *block, ir_node *objptr, ir_node **mem); 9 | 10 | void dmemory_init(void); 11 | void dmemory_lower_Arraylength(ir_node* arraylength); 12 | void dmemory_set_allocation_methods(get_arraylength_t ga_func); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/liboo/eh.h: -------------------------------------------------------------------------------- 1 | #ifndef OO_EH_H 2 | #define OO_EH_H 3 | 4 | #include 5 | 6 | void eh_init(void); 7 | void eh_deinit(void); 8 | 9 | void eh_start_method(void); 10 | void eh_new_lpad(void); 11 | void eh_add_handler(ir_type *catch_type, ir_node *block); 12 | void eh_pop_lpad(void); 13 | void eh_end_method(void); 14 | 15 | ir_node *eh_get_exception_object(void); 16 | ir_node *eh_new_Call(ir_node * irn_ptr, int arity, ir_node *const * in, ir_type* catch_type); 17 | void eh_throw(ir_node *exo_ptr); 18 | 19 | void eh_lower_Raise(ir_node *raise, ir_node *proj); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/liboo/oo.h: -------------------------------------------------------------------------------- 1 | #ifndef OO_OO_H 2 | #define OO_OO_H 3 | 4 | #include 5 | #include 6 | 7 | #include "ddispatch.h" 8 | #include "rta.h" 9 | 10 | void oo_init(void); 11 | void oo_deinit(void); 12 | void oo_lower(void); 13 | 14 | void oo_set_interface_call_type(ddispatch_interface_call type); 15 | ddispatch_interface_call oo_get_interface_call_type(void); 16 | 17 | 18 | unsigned oo_get_class_uid(ir_type *classtype); 19 | void oo_set_class_uid(ir_type *classtype, unsigned uid); 20 | ir_entity *oo_get_class_vtable_entity(ir_type *classtype); 21 | void oo_set_class_vtable_entity(ir_type *classtype, ir_entity *vtable); 22 | unsigned oo_get_class_vtable_size(ir_type *classtype); 23 | void oo_set_class_vtable_size(ir_type *classtype, unsigned vtable_size); 24 | ir_entity *oo_get_class_vptr_entity(ir_type *classtype); 25 | void oo_set_class_vptr_entity(ir_type *classtype, ir_entity *vptr); 26 | ir_entity *oo_get_class_rtti_entity(ir_type *classtype); 27 | void oo_set_class_rtti_entity(ir_type *classtype, ir_entity *rtti); 28 | ir_entity *oo_get_class_itt_entity(ir_type *classtype); 29 | void oo_set_class_itt_entity(ir_type *classtype, ir_entity *itt); 30 | bool oo_get_class_is_interface(ir_type *classtype); 31 | void oo_set_class_is_interface(ir_type *classtype, bool is_interface); 32 | bool oo_get_class_is_abstract(ir_type *classtype); 33 | void oo_set_class_is_abstract(ir_type *classtype, bool is_abstract); 34 | bool oo_get_class_is_final(ir_type *classtype); 35 | void oo_set_class_is_final(ir_type *classtype, bool is_final); 36 | bool oo_get_class_is_extern(ir_type *classtype); 37 | void oo_set_class_is_extern(ir_type *classtype, bool is_extern); 38 | 39 | void *oo_get_type_link(ir_type *type); 40 | void oo_set_type_link(ir_type *type, void* link); 41 | 42 | bool oo_get_method_exclude_from_vtable(ir_entity *method); 43 | void oo_set_method_exclude_from_vtable(ir_entity *method, bool exclude_from_vtable); 44 | int oo_get_method_vtable_index(ir_entity *method); 45 | void oo_set_method_vtable_index(ir_entity *method, int vtable_slot); 46 | bool oo_get_method_is_abstract(ir_entity *method); 47 | void oo_set_method_is_abstract(ir_entity *method, bool is_abstract); 48 | bool oo_get_method_is_final(ir_entity *method); 49 | void oo_set_method_is_final(ir_entity *method, bool is_final); 50 | bool oo_get_method_is_inherited(ir_entity *method); 51 | void oo_set_method_is_inherited(ir_entity *method, bool is_inherited); 52 | 53 | bool oo_get_field_is_transient(ir_entity *field); 54 | void oo_set_field_is_transient(ir_entity *field, bool is_transient); 55 | 56 | ddispatch_binding oo_get_entity_binding(ir_entity *entity); 57 | void oo_set_entity_binding(ir_entity *entity, ddispatch_binding binding); 58 | void *oo_get_entity_link(ir_entity *entity); 59 | void oo_set_entity_link(ir_entity *entity, void* link); 60 | 61 | void oo_set_call_is_statically_bound(ir_node *call, bool bind_statically); 62 | bool oo_get_call_is_statically_bound(ir_node *call); 63 | 64 | ir_type *oo_get_class_superclass(ir_type *klass); 65 | ir_entity *oo_get_entity_overwritten_superclass_entity(ir_entity *entity); 66 | 67 | void oo_copy_entity_info(ir_entity *src, ir_entity *dest); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/liboo/opt.h: -------------------------------------------------------------------------------- 1 | #ifndef OO_OPT_H 2 | #define OO_OPT_H 3 | 4 | /** 5 | * register transform_Node/equivalent_node/computed_value optimization 6 | * callbacks for liboo specific nodes. 7 | */ 8 | void oo_register_opt_funcs(void); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/liboo/rta.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of liboo. 3 | */ 4 | 5 | /** 6 | * @file rta.h 7 | * @brief Devirtualization of dynamically bound calls through Rapid Type Analysis 8 | * @author Steffen Knoth 9 | * @date 2014 10 | */ 11 | 12 | 13 | #ifndef OO_RTA_H 14 | #define OO_RTA_H 15 | 16 | 17 | #include 18 | 19 | /** sets important callback functions needed to detect calls (e.g. class intialization) hidden behind frontend-specific nodes 20 | * @note It's very important for the frontend to implement these callbacks correctly, if anything is missing RTA's assumptions may not hold and it can lead to defective programs! 21 | * @note This mechanism is meant for functions similar to e.g. _Jv_InitClass that hide calls to analyzable methods in native code. 22 | * @note It doesn't make much sense to return entities of native functions or methods. Return methods that can and should be analyzed even if they are called indirectly by other native methods that are called by the method/function in question. 23 | * @note The callbacks are only called on statically bound call nodes that call a function that has no firm graph. 24 | * @param detect_call give function that returns the entity (ir_entity*) of the method called by the call node or NULL if no method is called //TODO support for more than one 25 | */ 26 | void rta_set_detection_callbacks(ir_entity *(*detect_call)(ir_node *call)); 27 | 28 | 29 | /** runs Rapid Type Analysis and then tries to devirtualize dynamically bound calls and to discard unneeded classes and methods 30 | * @note RTA requires object creations to be marked with VptrIsSet nodes. 31 | * @note RTA requires the analyzed code to be typesafe, meaning objects on which dynamically bound calls are invoked have to be of the static type of the reference or a subclass of it, otherwise the results can be incorrect and can lead to defective programs! 32 | * @note RTA must know of _all_ definitely executed code parts (main, class initializers, global contructors or all nonprivate functions if it's a library)! It's important to give absolutely _all_ entry points because RTA builds on a closed world assumption. Otherwise the results can be incorrect and can lead to defective programs! 33 | * @note RTA also won't work with programs that dynamically load classes at runtime or use generic object creation (like Java Class.newInstance)! It can lead to defective programs! 34 | * @note Give classes that are instantiated in native methods of a nonexternal standard library or runtime as initial_live_classes, give methods called in these native methods as additional entry points. If something is missing, RTA could produce defective programs! This also means that native methods in the program that do arbitrary things are not supported as long as there is no way to tell RTA what classes are instantiated and what methods are called in all those native methods. 35 | * @note C++ is currently not supported (C++ constructor semantics, function pointers, ...). 36 | * @param entry_points NULL-terminated array of method entities, give all entry points to program code, may _not_ be NULL and must contain at least one method entity, also all entry points should have a graph 37 | * @param initial_live_classes NULL-terminated array of classes that should always be considered live, may be NULL 38 | */ 39 | void rta_optimization(ir_entity** entry_points, ir_type **initial_live_classes); 40 | 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/liboo/rts_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * Structure of runtime type information as emitted by liboo. 4 | * 5 | * Warning: if you change this struct, also change the code in rtti.c which 6 | * emits this data during a compilation run 7 | */ 8 | #ifndef OO_RTS_TYPES_H 9 | #define OO_RTS_TYPES_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | typedef struct { 16 | uint32_t hash; 17 | char data[]; 18 | } string_const_t; 19 | 20 | typedef struct { 21 | string_const_t *name; /* including signature */ 22 | void *funcptr; 23 | } method_info_t; 24 | 25 | struct class_info_t { 26 | string_const_t *name; 27 | uint32_t uid; 28 | size_t size; 29 | struct class_info_t *superclass; 30 | uint32_t n_methods; 31 | method_info_t *methods; 32 | uint32_t n_interfaces; 33 | struct class_info_t **interfaces; 34 | }; 35 | typedef struct class_info_t class_info_t; 36 | 37 | typedef struct { 38 | void *ip; 39 | void *handler; 40 | } lsda_entry_t; 41 | 42 | typedef struct { 43 | uint32_t n_entries; 44 | lsda_entry_t entries[1]; 45 | } lsda_t; 46 | 47 | inline static const char *get_string_const_chars(const string_const_t *s) 48 | { 49 | return s->data; 50 | } 51 | 52 | inline static uint32_t string_hash(const char* s) 53 | { 54 | uint32_t hash = 0; 55 | for (const char *c = s; *c != '\0'; ++c) { 56 | hash = (31 * hash) ^ *c; 57 | } 58 | return hash; 59 | } 60 | 61 | inline static bool string_const_equals(const string_const_t *s1, 62 | const string_const_t *s2) 63 | { 64 | /* cannot be equal if hashes don't match */ 65 | if (s1->hash != s2->hash) 66 | return false; 67 | if (s1 == s2) 68 | return true; 69 | 70 | char *p1 = (char*)&s1->data; 71 | char *p2 = (char*)&s2->data; 72 | while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) { 73 | p1++; p2++; 74 | } 75 | /* true if both strings reached the end (and thus must be equal) */ 76 | return (*p1 == '\0' && *p2 == '\0'); 77 | 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /include/liboo/rtti.h: -------------------------------------------------------------------------------- 1 | #ifndef OO_RTTI_H 2 | #define OO_RTTI_H 3 | 4 | #include 5 | 6 | typedef void (*construct_runtime_typeinfo_t) (ir_type *klass); 7 | typedef ir_node *(*construct_instanceof_t) (ir_node *objptr, ir_type *klass, ir_graph *irg, ir_node *block, ir_node **mem); 8 | 9 | void rtti_default_construct_runtime_typeinfo(ir_type *klass); 10 | ir_node *rtti_default_construct_instanceof(ir_node *objptr, ir_type *klass, ir_graph *irg, ir_node *block, ir_node **mem); 11 | 12 | void rtti_init(void); 13 | void rtti_deinit(void); 14 | void rtti_construct_runtime_typeinfo(ir_type *klass); 15 | void rtti_lower_InstanceOf(ir_node *instanceof); 16 | void rtti_set_runtime_typeinfo_constructor(construct_runtime_typeinfo_t func); 17 | void rtti_set_instanceof_constructor(construct_instanceof_t func); 18 | 19 | ir_entity *rtti_emit_string_const(const char *bytes); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /spec/config.example: -------------------------------------------------------------------------------- 1 | FIRM_HOME="../../libfirm" 2 | FIRM_INC="${FIRM_HOME}/include" 3 | FIRM_INC2="${FIRM_HOME}/build/gen/include/libfirm" 4 | FIRM_BUILD="${FIRM_HOME}/build/debug/" 5 | -------------------------------------------------------------------------------- /spec/generate_headerbindings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # You need a new version cparser (with jna backend) and firm headers 4 | set -eu 5 | 6 | . ./config 7 | 8 | for i in oo nodes rta ; do 9 | RES="../src/firm/bindings/binding_$i.java" 10 | TMP="/tmp/tmp.java" 11 | TMP2="/tmp/tmp2.java" 12 | OO_INC="../include" 13 | echo " * Creating $RES" 14 | CMD="cparser --print-jna --jna-libname oo -I${FIRM_INC} -I${FIRM_INC2} -I${OO_INC} ${OO_INC}/liboo/$i.h --jna-limit ${OO_INC}/liboo/$i.h" 15 | echo "$CMD" 16 | $CMD > $TMP || exit $? 17 | sed -e "s/class binding/class binding_$i/g" -i $TMP 18 | echo "package firm.bindings;" > $TMP2 19 | echo "" >> $TMP2 20 | cat $TMP2 $TMP > $RES 21 | done 22 | 23 | -------------------------------------------------------------------------------- /spec/javagen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | FIRM_HOME="../../libfirm" 6 | JFIRM_HOME="../../jFirm" 7 | GENERATOR="python ${FIRM_HOME}/scripts/gen_ir.py -I${JFIRM_HOME}/binding_generator -I. javaspec.py" 8 | 9 | #$GENERATOR templates/Node.java 10 | echo "Create: Nodes.java" 11 | $GENERATOR templates/Nodes.java > ../src/firm/oo/nodes/Nodes.java 12 | 13 | $GENERATOR templates/nodelist > /tmp/nodelist 14 | for n in $(cat /tmp/nodelist); do 15 | GOAL="../src/firm/oo/nodes/$n.java" 16 | echo "GEN $GOAL" 17 | $GENERATOR -DNODENAME=$n templates/Node.java > $GOAL 18 | done 19 | -------------------------------------------------------------------------------- /spec/javaspec.py: -------------------------------------------------------------------------------- 1 | from oo_nodes_spec import nodes, abstract_nodes 2 | from javabits import preprocess_node 3 | from jinjautil import export 4 | 5 | java_binding = "firm.bindings.binding_nodes" 6 | java_package = "firm.oo.nodes" 7 | export(java_package, "java_package") 8 | export(java_binding, "java_binding") 9 | 10 | for node in nodes+abstract_nodes: 11 | preprocess_node(node) 12 | -------------------------------------------------------------------------------- /spec/oo_nodes_spec.py: -------------------------------------------------------------------------------- 1 | from irops import op, Attribute, prepare_nodes, Node 2 | from jinjautil import export 3 | 4 | name = "oo" 5 | external = "liboo" 6 | 7 | @op 8 | class InstanceOf(Node): 9 | """Check if an object is an instance of a specified type (or a subtype). 10 | Passing a null pointer results in undefined behaviour.""" 11 | ins = [ 12 | ("mem", "memory dependency"), 13 | ("ptr", "pointer to object"), 14 | ] 15 | outs = [ 16 | ("M", "memory result"), 17 | ("res", "result of instanceof check"), # mode_b 18 | ] 19 | attrs = [ 20 | Attribute("type", type="ir_type*", comment="classtype to check for"), 21 | ] 22 | flags = [ "uses_memory" ] 23 | pinned = "no" 24 | attr_struct = "op_InstanceOf_attr_t" 25 | 26 | @op 27 | class Arraylength(Node): 28 | """Return the lenght of a (dynamic) array""" 29 | ins = [ 30 | ("mem", "memory dependency"), 31 | ("ptr", "pointer to array"), 32 | ] 33 | outs = [ 34 | ("M", "memory result"), 35 | ("res", "length of the array"), 36 | ] 37 | flags = [ "uses_memory" ] 38 | pinned = "no" 39 | 40 | @op 41 | class MethodSel(Node): 42 | """Performs a vtable lookup for a method (or rtti info).""" 43 | ins = [ 44 | ("mem", "memory dependency"), 45 | ("ptr", "pointer to an object with a vtable"), 46 | ] 47 | outs = [ 48 | ("M", "memory result"), 49 | ("res", "address of method"), 50 | ] 51 | attrs = [ 52 | Attribute("entity", type="ir_entity*", 53 | comment="method entity which should be selected"), 54 | ] 55 | attr_struct = "op_MethodSel_attr_t" 56 | flags = [ "uses_memory" ] 57 | pinned = "no" 58 | 59 | @op 60 | class VptrIsSet(Node): 61 | """Mark that an objects vptr has been set. This node duplicates its pointer 62 | input and guarantees that all users of this node have an object of the 63 | specified type. 64 | 65 | In practice you would put such a node behind allocation calls in a java-like 66 | language or behind an external constructor call in a C++-like language. 67 | 68 | You could think of this as a special case of Confirm node, ensuring a 69 | certain object type.""" 70 | ins = [ 71 | ("mem", "memory dependency"), 72 | ("ptr", "pointer to an object"), 73 | ] 74 | outs = [ 75 | ("M", "memory result"), 76 | ("res", "pointer to object"), 77 | ] 78 | attrs = [ 79 | Attribute("type", type="ir_type*", 80 | comment="type of the object"), 81 | ] 82 | attr_struct = "op_VptrIsSet_attr_t" 83 | flags = [ "uses_memory" ] 84 | pinned = "no" 85 | 86 | (nodes, abstract_nodes) = prepare_nodes(globals()) 87 | export(nodes, "nodes") 88 | export(abstract_nodes, "abstract_nodes") 89 | export(globals(), "spec") 90 | -------------------------------------------------------------------------------- /src-cpp/adt/align.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief macros for alignment. 23 | * @author Markus Armbruster 24 | * @version $Id: align.h 17143 2008-01-02 20:56:33Z beck $ 25 | */ 26 | #ifndef FIRM_ADT_ALIGN_H 27 | #define FIRM_ADT_ALIGN_H 28 | 29 | #include 30 | 31 | /** A size handled efficiently by malloc(), at least 1K. */ 32 | #define PREF_MALLOC_SIZE 2048 33 | 34 | 35 | /** A wrapper around GNU C's __attribute__ */ 36 | 37 | /* According to the documentation, the attributes we are interested in 38 | work with 2.5, but we encountered trouble before 2.7. */ 39 | #if defined (__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 7 40 | # define HAVE_ATTRIBUTE 1 41 | # define ATTRIBUTE(attrs) __attribute__ (attrs) 42 | #else 43 | # define ATTRIBUTE(attrs) 44 | #endif 45 | 46 | 47 | /* Alignment */ 48 | 49 | /** A type that has most constrained alignment. */ 50 | typedef union { 51 | long double d; 52 | void *p; 53 | long l; 54 | } aligned_type ATTRIBUTE ((aligned)); 55 | 56 | /** Inquiring about the alignment of a type. */ 57 | #ifdef __GNUC__ 58 | # define ALIGNOF(type) __alignof__ (type) 59 | #else 60 | # define ALIGNOF(type) offsetof (struct { char c; type d; }, d) 61 | #endif 62 | 63 | /** Maximal alignment required for any type. */ 64 | #define MAX_ALIGN ALIGNOF (aligned_type) 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src-cpp/adt/array.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /src-cpp/adt/bitfiddle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @date 28.9.2004 23 | * @brief Functions from hackers delight. 24 | * @author Sebastian Hack, Matthias Braun 25 | * @version $Id: bitfiddle.h 27155 2010-02-14 14:38:55Z mallon $ 26 | */ 27 | #ifndef FIRM_ADT_BITFIDDLE_H 28 | #define FIRM_ADT_BITFIDDLE_H 29 | 30 | #include "compiler.h" 31 | 32 | #include 33 | #include 34 | 35 | /* some functions here assume ints are 32 bit wide */ 36 | #define HACKDEL_WORDSIZE 32 37 | COMPILETIME_ASSERT(sizeof(unsigned) == 4, unsignedsize) 38 | COMPILETIME_ASSERT(UINT_MAX == 4294967295U, uintmax) 39 | 40 | /** 41 | * Add saturated. 42 | * @param x Summand 1. 43 | * @param y Summand 2. 44 | * @return x + y or INT_MAX/INT_MIN if an overflow occurred and x,y was positive/negative. 45 | * 46 | * @note See hacker's delight, page 27. 47 | */ 48 | static inline int add_saturated(int x, int y) 49 | { 50 | int sum = x + y; 51 | /* 52 | An overflow occurs, if the sign of the both summands is equal 53 | and the one of the sum is different from the summand's one. 54 | The sign bit is 1, if an overflow occurred, 0 otherwise. 55 | int overflow = ~(x ^ y) & (sum ^ x); 56 | */ 57 | int overflow = (x ^ sum) & (y ^ sum); 58 | 59 | /* 60 | The infinity to use. 61 | Make a mask of the sign bit of x and y (they are the same if an 62 | overflow occurred). 63 | INT_MIN == ~INT_MAX, so if the sign was negative, INT_MAX becomes 64 | INT_MIN. 65 | */ 66 | int inf = (x >> (sizeof(x) * 8 - 1)) ^ INT_MAX; 67 | 68 | return overflow < 0 ? inf : sum; 69 | } 70 | 71 | /** 72 | * Compute the count of set bits in a 32-bit word. 73 | * @param x A 32-bit word. 74 | * @return The number of bits set in x. 75 | */ 76 | static inline unsigned popcnt(unsigned x) 77 | { 78 | x -= ((x >> 1) & 0x55555555); 79 | x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 80 | x = (x + (x >> 4)) & 0x0f0f0f0f; 81 | x += x >> 8; 82 | x += x >> 16; 83 | return x & 0x3f; 84 | } 85 | 86 | /** 87 | * Compute the number of leading zeros in a word. 88 | * @param x The word. 89 | * @return The number of leading (from the most significant bit) zeros. 90 | */ 91 | static inline unsigned nlz(unsigned x) 92 | { 93 | #ifdef USE_X86_ASSEMBLY 94 | unsigned res; 95 | if(x == 0) 96 | return 32; 97 | 98 | __asm__("bsrl %1,%0" 99 | : "=r" (res) 100 | : "r" (x)); 101 | return 31 - res; 102 | #else 103 | unsigned y; 104 | int n = 32; 105 | 106 | y = x >>16; if (y != 0) { n -= 16; x = y; } 107 | y = x >> 8; if (y != 0) { n -= 8; x = y; } 108 | y = x >> 4; if (y != 0) { n -= 4; x = y; } 109 | y = x >> 2; if (y != 0) { n -= 2; x = y; } 110 | y = x >> 1; if (y != 0) return n - 2; 111 | return n - x; 112 | #endif 113 | } 114 | 115 | /** 116 | * Compute the number of trailing zeros in a word. 117 | * @param x The word. 118 | * @return The number of trailing zeros. 119 | */ 120 | static inline unsigned ntz(unsigned x) 121 | { 122 | #ifdef USE_X86_ASSEMBLY 123 | unsigned res; 124 | if(x == 0) 125 | return 32; 126 | 127 | __asm__("bsfl %1,%0" 128 | : "=r" (res) 129 | : "r" (x)); 130 | return res; 131 | #else 132 | return HACKDEL_WORDSIZE - nlz(~x & (x - 1)); 133 | #endif 134 | } 135 | 136 | /** 137 | * Compute the greatest power of 2 smaller or equal to a value. 138 | * This is also known as the binary logarithm. 139 | * @param x The value. 140 | * @return The power of two. 141 | */ 142 | #define log2_floor(x) (HACKDEL_WORDSIZE - 1 - nlz(x)) 143 | 144 | /** 145 | * Compute the smallest power of 2 greater or equal to a value. 146 | * This is also known as the binary logarithm. 147 | * @param x The value. 148 | * @return The power of two. 149 | */ 150 | #define log2_ceil(x) (HACKDEL_WORDSIZE - nlz((x) - 1)) 151 | 152 | /** 153 | * Round up to the next multiple of a power of two. 154 | * @param x A value. 155 | * @param pot A power of two. 156 | * @return x rounded up to the next multiple of pot. 157 | */ 158 | #define round_up2(x,pot) (((x) + ((pot) - 1)) & (~((pot) - 1))) 159 | 160 | /** 161 | * Returns the biggest power of 2 that is equal or smaller than @p x 162 | * (see hackers delight power-of-2 boundaries, page 48) 163 | */ 164 | static inline unsigned floor_po2(unsigned x) 165 | { 166 | #ifdef USE_X86_ASSEMBLY // in this case nlz is fast 167 | if(x == 0) 168 | return 0; 169 | // note that x != 0 here, so nlz(x) < 32! 170 | return 0x80000000U >> nlz(x); 171 | #else 172 | x |= x >> 1; 173 | x |= x >> 2; 174 | x |= x >> 4; 175 | x |= x >> 8; 176 | x |= x >> 16; 177 | return x - (x >> 1); 178 | #endif 179 | } 180 | 181 | /** 182 | * Returns the smallest power of 2 that is equal or greater than x 183 | * @remark x has to be <= 0x8000000 of course 184 | * @note see hackers delight power-of-2 boundaries, page 48 185 | */ 186 | static inline unsigned ceil_po2(unsigned x) 187 | { 188 | if(x == 0) 189 | return 0; 190 | assert(x < (1U << 31)); 191 | 192 | #ifdef USE_X86_ASSEMBLY // in this case nlz is fast 193 | // note that x != 0 here! 194 | return 0x80000000U >> (nlz(x-1) - 1); 195 | #else 196 | x = x - 1; 197 | x |= x >> 1; 198 | x |= x >> 2; 199 | x |= x >> 4; 200 | x |= x >> 8; 201 | x |= x >> 16; 202 | return x + 1; 203 | #endif 204 | } 205 | 206 | /** 207 | * Tests whether @p x is a power of 2 208 | */ 209 | static inline int is_po2(unsigned x) 210 | { 211 | return (x & (x-1)) == 0; 212 | } 213 | 214 | #endif 215 | -------------------------------------------------------------------------------- /src-cpp/adt/compiler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @date 04.06.2007 23 | * @author Matthias Braun, Sebastian Hack 24 | * @brief Macros to instruct the compiler compiling libFirm. 25 | */ 26 | 27 | #ifndef FIRM_COMPILER_H 28 | #define FIRM_COMPILER_H 29 | 30 | /** 31 | * Asserts that the constant expression x is not zero at compiletime. name has 32 | * to be a unique identifier. 33 | * 34 | * @note This uses the fact, that double case labels are not allowed. 35 | */ 36 | #define COMPILETIME_ASSERT(x, name) \ 37 | static __attribute__((unused)) void compiletime_assert_##name (int h) { \ 38 | switch(h) { case 0: case (x): ; } \ 39 | } 40 | 41 | #ifdef __GNUC__ 42 | /** 43 | * Indicates to the compiler that the value of x is very likely 1 44 | * @note Only use this in speed critical code and when you are sure x is often 1 45 | */ 46 | #define LIKELY(x) __builtin_expect((x), 1) 47 | 48 | /** 49 | * Indicates to the compiler that it's very likely that x is 0 50 | * @note Only use this in speed critical code and when you are sure x is often 0 51 | */ 52 | #define UNLIKELY(x) __builtin_expect((x), 0) 53 | 54 | /** 55 | * Tell the compiler, that a function is pure, i.e. it only 56 | * uses its parameters and never modifies the "state". 57 | * Add this macro after the return type. 58 | */ 59 | #define PURE __attribute__((const)) 60 | 61 | #else 62 | #define LIKELY(x) x 63 | #define UNLIKELY(x) x 64 | #define PURE 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src-cpp/adt/cpmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief Custom pointer set 23 | * @author Matthias Braun 24 | * @version $Id: cpmap.c 17143 2008-01-02 20:56:33Z beck $ 25 | * 26 | * This implements a set of pointers which allows to specify custom callbacks 27 | * for comparing and hashing it's elements. 28 | */ 29 | #include "cpmap.h" 30 | 31 | #define HashSet cpmap_t 32 | #define HashSetIterator cpmap_iterator_t 33 | #define HashSetEntry cpmap_hashset_entry_t 34 | #define ValueType cpmap_entry_t 35 | #define NullValue (cpmap_entry_t) { NULL, NULL } 36 | #define DeletedValue (cpmap_entry_t) { ((void*)-1), NULL } 37 | #define KeyType const void* 38 | #define ConstKeyType KeyType 39 | #define GetKey(value) (value).key 40 | #define InitData(self,value,k) (value).key = (k) 41 | #define Hash(this,key) this->hash_function(key) 42 | #define KeysEqual(this,key1,key2) this->cmp_function(key1, key2) 43 | #define SetRangeEmpty(ptr,size) memset(ptr, 0, (size) * sizeof(HashSetEntry)) 44 | #define EntryIsEmpty(entry) (EntryGetValue(entry).key == NULL) 45 | #define EntryIsDeleted(entry) (EntryGetValue(entry).key == ((void*)-1)) 46 | 47 | void cpmap_init_(cpmap_t *map); 48 | #define hashset_init cpmap_init_ 49 | void cpmap_init_size_(cpmap_t *map, size_t size); 50 | #define hashset_init_size cpmap_init_size_ 51 | #define hashset_destroy cpmap_destroy 52 | cpmap_entry_t *cpmap_insert_(cpmap_t *map, const void *key); 53 | #define hashset_insert cpmap_insert_ 54 | #define hashset_remove cpmap_remove 55 | cpmap_entry_t *cpmap_find_(const cpmap_t *map, const void *key); 56 | #define hashset_find cpmap_find_ 57 | #define hashset_size cpmap_size 58 | #define hashset_iterator_init cpmap_iterator_init 59 | #define hashset_iterator_next cpmap_iterator_next 60 | #define hashset_remove_iterator cpmap_remove_iterator 61 | 62 | #include "hashset.c.h" 63 | 64 | void cpmap_init(cpmap_t *map, cpmap_hash_function hash_function, 65 | cpmap_cmp_function cmp_function) 66 | { 67 | map->hash_function = hash_function; 68 | map->cmp_function = cmp_function; 69 | cpmap_init_(map); 70 | } 71 | 72 | void cpmap_init_size(cpmap_t *map, cpmap_hash_function hash_function, 73 | cpmap_cmp_function cmp_function, size_t expected_elems) 74 | { 75 | map->hash_function = hash_function; 76 | map->cmp_function = cmp_function; 77 | cpmap_init_size_(map, expected_elems); 78 | } 79 | 80 | void cpmap_set(cpmap_t *map, const void *key, void *data) 81 | { 82 | if (data == NULL) { 83 | cpmap_remove(map, key); 84 | } else { 85 | cpmap_entry_t *entry = cpmap_insert_(map, key); 86 | entry->data = data; 87 | } 88 | } 89 | 90 | void *cpmap_find(const cpmap_t *map, const void *key) 91 | { 92 | cpmap_entry_t *entry = cpmap_find_(map, key); 93 | if (entry == NULL) 94 | return NULL; 95 | return entry->data; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src-cpp/adt/cpmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @date 16.03.2007 23 | * @brief a pointer to pointer map with a custom compare/hash functions 24 | * @author Matthias Braun 25 | * @version $Id$ 26 | */ 27 | #ifndef FIRM_ADT_CPMAP_H 28 | #define FIRM_ADT_CPMAP_H 29 | 30 | /** 31 | * The type of a cpmap compare function. 32 | * 33 | * @param p1 pointer to an element 34 | * @param p2 pointer to another element 35 | * 36 | * @return 1 if the elements are identically, zero else 37 | */ 38 | typedef int (*cpmap_cmp_function) (const void *p1, const void *p2); 39 | 40 | /** 41 | * The type of a cpmap hash function. 42 | */ 43 | typedef unsigned (*cpmap_hash_function) (const void *obj); 44 | 45 | typedef struct cpmap_entry_t { 46 | const void *key; 47 | void *data; 48 | } cpmap_entry_t; 49 | 50 | #define HashSet cpmap_t 51 | #define HashSetIterator cpmap_iterator_t 52 | #define HashSetEntry cpmap_hashset_entry_t 53 | #define ValueType cpmap_entry_t 54 | #define ADDITIONAL_DATA cpmap_cmp_function cmp_function; cpmap_hash_function hash_function; 55 | #include "hashset.h" 56 | #undef ADDITIONAL_DATA 57 | #undef ValueType 58 | #undef HashSetEntry 59 | #undef HashSetIterator 60 | #undef HashSet 61 | 62 | typedef struct cpmap_t cpmap_t; 63 | typedef struct cpmap_iterator_t cpmap_iterator_t; 64 | 65 | /** 66 | * Initializes a cpmap 67 | * 68 | * @param cpmap Pointer to allocated space for the cpmap 69 | * @param hash_function The hash function to use 70 | * @param cmp_function The compare function to use 71 | */ 72 | void cpmap_init(cpmap_t *cpmap, cpmap_hash_function hash_function, 73 | cpmap_cmp_function cmp_function); 74 | 75 | /** 76 | * Initializes a cpmap 77 | * 78 | * @param cpmap Pointer to allocated space for the cpmap 79 | * @param hash_function The hash function to use 80 | * @param cmp_function The compare function to use 81 | * @param expected_elements Number of elements expected in the cpmap (roughly) 82 | */ 83 | void cpmap_init_size(cpmap_t *cpmap, cpmap_hash_function hash_function, 84 | cpmap_cmp_function cmp_function, 85 | size_t expected_elements); 86 | 87 | /** 88 | * Destroys a cpmap and frees the memory allocated for hashtable. The memory of 89 | * the cpmap itself is not freed. 90 | * 91 | * @param cpmap Pointer to the cpmap 92 | */ 93 | void cpmap_destroy(cpmap_t *cpmap); 94 | 95 | /** 96 | * Inserts an element into a cpmap. 97 | * 98 | * @param cpmap Pointer to the cpmap 99 | * @param key key under which we file the data 100 | * @param obj the data (we just store a pointer to it) 101 | * @returns The element itself or a pointer to an existing element 102 | */ 103 | void cpmap_set(cpmap_t *cpmap, const void *key, void *data); 104 | 105 | /** 106 | * Removes an element from a cpmap. Does nothing if the cpmap doesn't contain 107 | * the element. 108 | * 109 | * @param cpmap Pointer to the cpmap 110 | * @param key key of the data to remove 111 | */ 112 | void cpmap_remove(cpmap_t *cpmap, const void *key); 113 | 114 | /** 115 | * Tests whether a cpmap contains a pointer 116 | * 117 | * @param cpmap Pointer to the cpmap 118 | * @param key Key of the data to find 119 | * @returns The data or NULL if not found 120 | */ 121 | void *cpmap_find(const cpmap_t *cpmap, const void *key); 122 | 123 | /** 124 | * Returns the number of pointers contained in the cpmap 125 | * 126 | * @param cpmap Pointer to the cpmap 127 | * @returns Number of pointers contained in the cpmap 128 | */ 129 | size_t cpmap_size(const cpmap_t *cpmap); 130 | 131 | /** 132 | * Initializes a cpmap iterator. Sets the iterator before the first element in 133 | * the cpmap. 134 | * 135 | * @param iterator Pointer to already allocated iterator memory 136 | * @param cpmap Pointer to the cpmap 137 | */ 138 | void cpmap_iterator_init(cpmap_iterator_t *iterator, const cpmap_t *cpmap); 139 | 140 | /** 141 | * Advances the iterator and returns the current element or NULL if all elements 142 | * in the cpmap have been processed. 143 | * @attention It is not allowed to use cpmap_set or cpmap_remove while 144 | * iterating over a cpmap. 145 | * 146 | * @param iterator Pointer to the cpmap iterator. 147 | * @returns Next element in the cpmap or NULL 148 | */ 149 | cpmap_entry_t cpmap_iterator_next(cpmap_iterator_t *iterator); 150 | 151 | /** 152 | * Removed the element the iterator currently points to 153 | * 154 | * @param cpmap Pointer to the cpmap 155 | * @param iterator Pointer to the cpmap iterator. 156 | */ 157 | void cpmap_remove_iterator(cpmap_t *cpmap, const cpmap_iterator_t *iterator); 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /src-cpp/adt/cpset.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief Custom pointer set 23 | * @author Matthias Braun 24 | * @version $Id: cpset.c 17143 2008-01-02 20:56:33Z beck $ 25 | * 26 | * This implements a set of pointers which allows to specify custom callbacks 27 | * for comparing and hashing it's elements. 28 | */ 29 | #include "cpset.h" 30 | 31 | #define HashSet cpset_t 32 | #define HashSetIterator cpset_iterator_t 33 | #define HashSetEntry cpset_hashset_entry_t 34 | #define ValueType void* 35 | #define NullValue NULL 36 | #define DeletedValue ((void*)-1) 37 | #define Hash(this,key) this->hash_function(key) 38 | #define KeysEqual(this,key1,key2) this->cmp_function(key1, key2) 39 | #define SCALAR_RETURN 40 | #define SetRangeEmpty(ptr,size) memset(ptr, 0, (size) * sizeof(cpset_hashset_entry_t)) 41 | 42 | void cpset_init_(cpset_t *set); 43 | #define hashset_init cpset_init_ 44 | void cpset_init_size_(cpset_t *set, size_t size); 45 | #define hashset_init_size cpset_init_size_ 46 | #define hashset_destroy cpset_destroy 47 | #define hashset_insert cpset_insert 48 | #define hashset_remove cpset_remove 49 | #define hashset_find cpset_find 50 | #define hashset_size cpset_size 51 | #define hashset_iterator_init cpset_iterator_init 52 | #define hashset_iterator_next cpset_iterator_next 53 | #define hashset_remove_iterator cpset_remove_iterator 54 | 55 | #include "hashset.c.h" 56 | 57 | void cpset_init(cpset_t *set, cpset_hash_function hash_function, 58 | cpset_cmp_function cmp_function) 59 | { 60 | set->hash_function = hash_function; 61 | set->cmp_function = cmp_function; 62 | cpset_init_(set); 63 | } 64 | 65 | void cpset_init_size(cpset_t *set, cpset_hash_function hash_function, 66 | cpset_cmp_function cmp_function, size_t expected_elems) 67 | { 68 | set->hash_function = hash_function; 69 | set->cmp_function = cmp_function; 70 | cpset_init_size_(set, expected_elems); 71 | } 72 | -------------------------------------------------------------------------------- /src-cpp/adt/cpset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @date 16.03.2007 23 | * @brief a set of pointers with a custom compare function 24 | * @author Matthias Braun 25 | * @version $Id: cpset.h 26416 2009-08-24 16:50:07Z buchwald $ 26 | */ 27 | #ifndef FIRM_ADT_CPSET_H 28 | #define FIRM_ADT_CPSET_H 29 | 30 | /** 31 | * The type of a cpset compare function. 32 | * 33 | * @param p1 pointer to an element 34 | * @param p2 pointer to another element 35 | * 36 | * @return 1 if the elements are identically, zero else 37 | */ 38 | typedef int (*cpset_cmp_function) (const void *p1, const void *p2); 39 | 40 | /** 41 | * The type of a cpset hash function. 42 | */ 43 | typedef unsigned (*cpset_hash_function) (const void *obj); 44 | 45 | #define HashSet cpset_t 46 | #define HashSetIterator cpset_iterator_t 47 | #define HashSetEntry cpset_hashset_entry_t 48 | #define ValueType void* 49 | #define ADDITIONAL_DATA cpset_cmp_function cmp_function; cpset_hash_function hash_function; 50 | #include "hashset.h" 51 | #undef ADDITIONAL_DATA 52 | #undef ValueType 53 | #undef HashSetEntry 54 | #undef HashSetIterator 55 | #undef HashSet 56 | 57 | typedef struct cpset_t cpset_t; 58 | typedef struct cpset_iterator_t cpset_iterator_t; 59 | 60 | /** 61 | * Initializes a cpset 62 | * 63 | * @param cpset Pointer to allocated space for the cpset 64 | * @param hash_function The hash function to use 65 | * @param cmp_function The compare function to use 66 | */ 67 | void cpset_init(cpset_t *cpset, cpset_hash_function hash_function, 68 | cpset_cmp_function cmp_function); 69 | 70 | /** 71 | * Initializes a cpset 72 | * 73 | * @param cpset Pointer to allocated space for the cpset 74 | * @param hash_function The hash function to use 75 | * @param cmp_function The compare function to use 76 | * @param expected_elements Number of elements expected in the cpset (roughly) 77 | */ 78 | void cpset_init_size(cpset_t *cpset, cpset_hash_function hash_function, 79 | cpset_cmp_function cmp_function, 80 | size_t expected_elements); 81 | 82 | /** 83 | * Destroys a cpset and frees the memory allocated for hashtable. The memory of 84 | * the cpset itself is not freed. 85 | * 86 | * @param cpset Pointer to the cpset 87 | */ 88 | void cpset_destroy(cpset_t *cpset); 89 | 90 | /** 91 | * Inserts an element into a cpset. 92 | * 93 | * @param cpset Pointer to the cpset 94 | * @param obj Element to insert into the cpset 95 | * @returns The element itself or a pointer to an existing element 96 | */ 97 | void* cpset_insert(cpset_t *cpset, void *obj); 98 | 99 | /** 100 | * Removes an element from a cpset. Does nothing if the cpset doesn't contain the 101 | * element. 102 | * 103 | * @param cpset Pointer to the cpset 104 | * @param obj Pointer to remove from the cpset 105 | */ 106 | void cpset_remove(cpset_t *cpset, const void *obj); 107 | 108 | /** 109 | * Tests whether a cpset contains a pointer 110 | * 111 | * @param cpset Pointer to the cpset 112 | * @param obj The pointer to find 113 | * @returns An equivalent object to @p obj or NULL 114 | */ 115 | void *cpset_find(const cpset_t *cpset, const void *obj); 116 | 117 | /** 118 | * Returns the number of pointers contained in the cpset 119 | * 120 | * @param cpset Pointer to the cpset 121 | * @returns Number of pointers contained in the cpset 122 | */ 123 | size_t cpset_size(const cpset_t *cpset); 124 | 125 | /** 126 | * Initializes a cpset iterator. Sets the iterator before the first element in 127 | * the cpset. 128 | * 129 | * @param iterator Pointer to already allocated iterator memory 130 | * @param cpset Pointer to the cpset 131 | */ 132 | void cpset_iterator_init(cpset_iterator_t *iterator, const cpset_t *cpset); 133 | 134 | /** 135 | * Advances the iterator and returns the current element or NULL if all elements 136 | * in the cpset have been processed. 137 | * @attention It is not allowed to use cpset_insert or cpset_remove while 138 | * iterating over a cpset. 139 | * 140 | * @param iterator Pointer to the cpset iterator. 141 | * @returns Next element in the cpset or NULL 142 | */ 143 | void *cpset_iterator_next(cpset_iterator_t *iterator); 144 | 145 | /** 146 | * Removed the element the iterator currently points to 147 | * 148 | * @param cpset Pointer to the cpset 149 | * @param iterator Pointer to the cpset iterator. 150 | */ 151 | void cpset_remove_iterator(cpset_t *cpset, const cpset_iterator_t *iterator); 152 | 153 | #endif /* FIRM_ADT_CPSET_H */ 154 | -------------------------------------------------------------------------------- /src-cpp/adt/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of cparser. 3 | * Copyright (C) 2007-2009 Matthias Braun 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 18 | * 02111-1307, USA. 19 | */ 20 | #include 21 | #include 22 | #include 23 | 24 | static inline __attribute__((noreturn, format(printf, 1, 2))) 25 | void panic(const char *fmt, ...) 26 | { 27 | va_list ap; 28 | va_start(ap, fmt); 29 | fputs("Panic: ", stderr); 30 | vfprintf(stderr, fmt, ap); 31 | fputc('\n', stderr); 32 | va_end(ap); 33 | 34 | abort(); 35 | } 36 | -------------------------------------------------------------------------------- /src-cpp/adt/fourcc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief Define the famous infame FOURCC macro. 23 | * @date 02.01.2004 24 | * @version $Id: fourcc.h 17143 2008-01-02 20:56:33Z beck $ 25 | */ 26 | #ifndef FIRM_ADT_FOURCC_H 27 | #define FIRM_ADT_FOURCC_H 28 | 29 | /** define a readable fourcc code */ 30 | #define FOURCC(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src-cpp/adt/hashptr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief Hash function for pointers 23 | * @author Michael Beck, Sebastian Hack 24 | * @version $Id: hashptr.h 26956 2010-01-13 15:41:28Z matze $ 25 | */ 26 | #ifndef FIRM_ADT_HASHPTR_H 27 | #define FIRM_ADT_HASHPTR_H 28 | 29 | #define _FIRM_FNV_OFFSET_BASIS 2166136261U 30 | #define _FIRM_FNV_FNV_PRIME 16777619U 31 | 32 | /* Computing x * _FIRM_FNV_FNV_PRIME */ 33 | #define _FIRM_FNV_TIMES_PRIME(x) ((x) * _FIRM_FNV_FNV_PRIME) 34 | 35 | static inline unsigned firm_fnv_hash(const unsigned char *data, unsigned bytes) 36 | { 37 | unsigned i; 38 | unsigned hash = _FIRM_FNV_OFFSET_BASIS; 39 | 40 | for(i = 0; i < bytes; ++i) { 41 | hash = _FIRM_FNV_TIMES_PRIME(hash); 42 | hash ^= data[i]; 43 | } 44 | 45 | return hash; 46 | } 47 | 48 | static inline unsigned firm_fnv_hash_str(const char *data) 49 | { 50 | unsigned i; 51 | unsigned hash = _FIRM_FNV_OFFSET_BASIS; 52 | 53 | for(i = 0; data[i] != '\0'; ++i) { 54 | hash = _FIRM_FNV_TIMES_PRIME(hash); 55 | hash ^= data[i]; 56 | } 57 | 58 | return hash; 59 | } 60 | 61 | /** 62 | * hash a pointer value: Pointer addresses are mostly aligned to 4 63 | * or 8 bytes. So we remove the lowest 3 bits 64 | */ 65 | #define HASH_PTR(ptr) ((unsigned)(((char *) (ptr) - (char *)0) >> 3)) 66 | 67 | static inline unsigned hash_ptr(const void *ptr) 68 | { 69 | return HASH_PTR(ptr); 70 | } 71 | 72 | /** 73 | * Hash a string. 74 | * @param str The string (can be const). 75 | * @param len The length of the string. 76 | * @return A hash value for the string. 77 | */ 78 | #define HASH_STR(str,len) firm_fnv_hash((const unsigned char *) (str), (len)) 79 | 80 | #ifdef _MSC_VER 81 | #pragma warning(disable:4307) 82 | #endif /* _MSC_VER */ 83 | 84 | static inline unsigned _hash_combine(unsigned x, unsigned y) 85 | { 86 | unsigned hash = _FIRM_FNV_TIMES_PRIME(_FIRM_FNV_OFFSET_BASIS); 87 | hash ^= x; 88 | hash = _FIRM_FNV_TIMES_PRIME(hash); 89 | hash ^= y; 90 | return hash; 91 | } 92 | 93 | #ifdef _MSC_VER 94 | #pragma warning(default:4307) 95 | #endif /* _MSC_VER */ 96 | 97 | /** 98 | * Make one hash value out of two others. 99 | * @param a One hash value. 100 | * @param b Another hash value. 101 | * @return A hash value computed from the both. 102 | */ 103 | #define HASH_COMBINE(a,b) _hash_combine(a, b) 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src-cpp/adt/hashset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of libFirm. 3 | * Copyright (C) 2012 University of Karlsruhe. 4 | */ 5 | 6 | /** 7 | * @file 8 | * @date 16.03.2007 9 | * @brief Generic hashset functions 10 | * @author Matthias Braun 11 | * 12 | * You have to specialize this header by defining HashSet, HashSetIterator and 13 | * ValueType 14 | */ 15 | #ifdef HashSet 16 | 17 | #include 18 | 19 | #ifdef DO_REHASH 20 | #define HashSetEntry ValueType 21 | #else 22 | typedef struct HashSetEntry { 23 | ValueType data; 24 | unsigned hash; 25 | } HashSetEntry; 26 | #endif 27 | 28 | struct HashSet { 29 | HashSetEntry *entries; 30 | size_t num_buckets; 31 | size_t enlarge_threshold; 32 | size_t shrink_threshold; 33 | size_t num_elements; 34 | size_t num_deleted; 35 | int consider_shrink; 36 | #ifndef NDEBUG 37 | unsigned entries_version; 38 | #endif 39 | #ifdef ADDITIONAL_DATA 40 | ADDITIONAL_DATA 41 | #endif 42 | }; 43 | 44 | #ifdef HashSetIterator 45 | struct HashSetIterator { 46 | HashSetEntry *current_bucket; 47 | HashSetEntry *end; 48 | #ifndef NDEBUG 49 | const struct HashSet *set; 50 | unsigned entries_version; 51 | #endif 52 | }; 53 | #endif 54 | 55 | #ifdef DO_REHASH 56 | #undef HashSetEntry 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src-cpp/adt/obst.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of cparser. 3 | * Copyright (C) 2007-2009 Matthias Braun 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 18 | * 02111-1307, USA. 19 | */ 20 | #include "obstack.h" 21 | #include "xmalloc.h" 22 | 23 | #define obstack_chunk_alloc xmalloc 24 | #define obstack_chunk_free free 25 | -------------------------------------------------------------------------------- /src-cpp/adt/obstack.c: -------------------------------------------------------------------------------- 1 | /* obstack.c - subroutines used implicitly by object stack macros 2 | Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 3 | 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 4 | This file is part of the GNU C Library. 5 | 6 | The GNU C Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | The GNU C Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with the GNU C Library; if not, write to the Free 18 | Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | Boston, MA 02110-1301, USA. */ 20 | #include "obstack.h" 21 | 22 | /* NOTE BEFORE MODIFYING THIS FILE: This version number must be 23 | incremented whenever callers compiled using an old obstack.h can no 24 | longer properly call the functions in this obstack.c. */ 25 | #define OBSTACK_INTERFACE_VERSION 1 26 | 27 | #include /* Random thing to get __GNU_LIBRARY__. */ 28 | #include 29 | #include 30 | 31 | /* Determine default alignment. */ 32 | union fooround 33 | { 34 | uintmax_t i; 35 | long double d; 36 | void *p; 37 | }; 38 | struct fooalign 39 | { 40 | char c; 41 | union fooround u; 42 | }; 43 | /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. 44 | But in fact it might be less smart and round addresses to as much as 45 | DEFAULT_ROUNDING. So we prepare for it to do that. */ 46 | enum 47 | { 48 | DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), 49 | DEFAULT_ROUNDING = sizeof (union fooround) 50 | }; 51 | 52 | /* When we copy a long block of data, this is the unit to do it with. 53 | On some machines, copying successive ints does not work; 54 | in such a case, redefine COPYING_UNIT to `long' (if that works) 55 | or `char' as a last resort. */ 56 | # ifndef COPYING_UNIT 57 | # define COPYING_UNIT int 58 | # endif 59 | 60 | 61 | /* The functions allocating more room by calling `obstack_chunk_alloc' 62 | jump to the handler pointed to by `obstack_alloc_failed_handler'. 63 | This can be set to a user defined function which should either 64 | abort gracefully or use longjump - but shouldn't return. This 65 | variable by default points to the internal function 66 | `print_and_abort'. */ 67 | static void print_and_abort (void); 68 | void (*obstack_alloc_failed_handler) (void) = print_and_abort; 69 | 70 | /* Exit value used when `print_and_abort' is used. */ 71 | # include 72 | int obstack_exit_failure = EXIT_FAILURE; 73 | 74 | /* Define a macro that either calls functions with the traditional malloc/free 75 | calling interface, or calls functions with the mmalloc/mfree interface 76 | (that adds an extra first argument), based on the state of use_extra_arg. 77 | For free, do not use ?:, since some compilers, like the MIPS compilers, 78 | do not allow (expr) ? void : void. */ 79 | 80 | # define CALL_CHUNKFUN(h, size) \ 81 | (((h) -> use_extra_arg) \ 82 | ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ 83 | : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) 84 | 85 | # define CALL_FREEFUN(h, old_chunk) \ 86 | do { \ 87 | if ((h) -> use_extra_arg) \ 88 | (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ 89 | else \ 90 | (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ 91 | } while (0) 92 | 93 | 94 | /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). 95 | Objects start on multiples of ALIGNMENT (0 means use default). 96 | CHUNKFUN is the function to use to allocate chunks, 97 | and FREEFUN the function to free them. 98 | 99 | Return nonzero if successful, calls obstack_alloc_failed_handler if 100 | allocation fails. */ 101 | 102 | int 103 | _obstack_begin (struct obstack *h, 104 | int size, int alignment, 105 | void *(*chunkfun) (long), 106 | void (*freefun) (void *)) 107 | { 108 | register struct _obstack_chunk *chunk; /* points to new chunk */ 109 | 110 | if (alignment == 0) 111 | alignment = DEFAULT_ALIGNMENT; 112 | if (size == 0) 113 | /* Default size is what GNU malloc can fit in a 4096-byte block. */ 114 | { 115 | /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. 116 | Use the values for range checking, because if range checking is off, 117 | the extra bytes won't be missed terribly, but if range checking is on 118 | and we used a larger request, a whole extra 4096 bytes would be 119 | allocated. 120 | 121 | These number are irrelevant to the new GNU malloc. I suspect it is 122 | less sensitive to the size of the request. */ 123 | int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) 124 | + 4 + DEFAULT_ROUNDING - 1) 125 | & ~(DEFAULT_ROUNDING - 1)); 126 | size = 4096 - extra; 127 | } 128 | 129 | h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; 130 | h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; 131 | h->chunk_size = size; 132 | h->alignment_mask = alignment - 1; 133 | h->use_extra_arg = 0; 134 | 135 | chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); 136 | if (!chunk) 137 | (*obstack_alloc_failed_handler) (); 138 | h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, 139 | alignment - 1); 140 | h->chunk_limit = chunk->limit 141 | = (char *) chunk + h->chunk_size; 142 | chunk->prev = 0; 143 | /* The initial chunk now contains no empty object. */ 144 | h->maybe_empty_object = 0; 145 | h->alloc_failed = 0; 146 | return 1; 147 | } 148 | 149 | int 150 | _obstack_begin_1 (struct obstack *h, int size, int alignment, 151 | void *(*chunkfun) (void *, long), 152 | void (*freefun) (void *, void *), 153 | void *arg) 154 | { 155 | register struct _obstack_chunk *chunk; /* points to new chunk */ 156 | 157 | if (alignment == 0) 158 | alignment = DEFAULT_ALIGNMENT; 159 | if (size == 0) 160 | /* Default size is what GNU malloc can fit in a 4096-byte block. */ 161 | { 162 | /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. 163 | Use the values for range checking, because if range checking is off, 164 | the extra bytes won't be missed terribly, but if range checking is on 165 | and we used a larger request, a whole extra 4096 bytes would be 166 | allocated. 167 | 168 | These number are irrelevant to the new GNU malloc. I suspect it is 169 | less sensitive to the size of the request. */ 170 | int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) 171 | + 4 + DEFAULT_ROUNDING - 1) 172 | & ~(DEFAULT_ROUNDING - 1)); 173 | size = 4096 - extra; 174 | } 175 | 176 | h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; 177 | h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; 178 | h->chunk_size = size; 179 | h->alignment_mask = alignment - 1; 180 | h->extra_arg = arg; 181 | h->use_extra_arg = 1; 182 | 183 | chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); 184 | if (!chunk) 185 | (*obstack_alloc_failed_handler) (); 186 | h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, 187 | alignment - 1); 188 | h->chunk_limit = chunk->limit 189 | = (char *) chunk + h->chunk_size; 190 | chunk->prev = 0; 191 | /* The initial chunk now contains no empty object. */ 192 | h->maybe_empty_object = 0; 193 | h->alloc_failed = 0; 194 | return 1; 195 | } 196 | 197 | /* Allocate a new current chunk for the obstack *H 198 | on the assumption that LENGTH bytes need to be added 199 | to the current object, or a new object of length LENGTH allocated. 200 | Copies any partial object from the end of the old chunk 201 | to the beginning of the new one. */ 202 | 203 | void 204 | _obstack_newchunk (struct obstack *h, int length) 205 | { 206 | register struct _obstack_chunk *old_chunk = h->chunk; 207 | register struct _obstack_chunk *new_chunk; 208 | register long new_size; 209 | register long obj_size = h->next_free - h->object_base; 210 | register long i; 211 | long already; 212 | char *object_base; 213 | 214 | /* Compute size for new chunk. */ 215 | new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100; 216 | if (new_size < h->chunk_size) 217 | new_size = h->chunk_size; 218 | 219 | /* Allocate and initialize the new chunk. */ 220 | new_chunk = CALL_CHUNKFUN (h, new_size); 221 | if (!new_chunk) 222 | (*obstack_alloc_failed_handler) (); 223 | h->chunk = new_chunk; 224 | new_chunk->prev = old_chunk; 225 | new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; 226 | 227 | /* Compute an aligned object_base in the new chunk */ 228 | object_base = 229 | __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); 230 | 231 | /* Move the existing object to the new chunk. 232 | Word at a time is fast and is safe if the object 233 | is sufficiently aligned. */ 234 | if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) 235 | { 236 | for (i = obj_size / sizeof (COPYING_UNIT) - 1; 237 | i >= 0; i--) 238 | ((COPYING_UNIT *)object_base)[i] 239 | = ((COPYING_UNIT *)h->object_base)[i]; 240 | /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, 241 | but that can cross a page boundary on a machine 242 | which does not do strict alignment for COPYING_UNITS. */ 243 | already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); 244 | } 245 | else 246 | already = 0; 247 | /* Copy remaining bytes one by one. */ 248 | for (i = already; i < obj_size; i++) 249 | object_base[i] = h->object_base[i]; 250 | 251 | /* If the object just copied was the only data in OLD_CHUNK, 252 | free that chunk and remove it from the chain. 253 | But not if that chunk might contain an empty object. */ 254 | if (! h->maybe_empty_object 255 | && (h->object_base 256 | == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, 257 | h->alignment_mask))) 258 | { 259 | new_chunk->prev = old_chunk->prev; 260 | CALL_FREEFUN (h, old_chunk); 261 | } 262 | 263 | h->object_base = object_base; 264 | h->next_free = h->object_base + obj_size; 265 | /* The new chunk certainly contains no empty object yet. */ 266 | h->maybe_empty_object = 0; 267 | } 268 | 269 | /* Return nonzero if object OBJ has been allocated from obstack H. 270 | This is here for debugging. 271 | If you use it in a program, you are probably losing. */ 272 | 273 | /* Suppress -Wmissing-prototypes warning. We don't want to declare this in 274 | obstack.h because it is just for debugging. */ 275 | int _obstack_allocated_p (struct obstack *h, void *obj); 276 | 277 | int 278 | _obstack_allocated_p (struct obstack *h, void *obj) 279 | { 280 | register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ 281 | register struct _obstack_chunk *plp; /* point to previous chunk if any */ 282 | 283 | lp = (h)->chunk; 284 | /* We use >= rather than > since the object cannot be exactly at 285 | the beginning of the chunk but might be an empty object exactly 286 | at the end of an adjacent chunk. */ 287 | while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) 288 | { 289 | plp = lp->prev; 290 | lp = plp; 291 | } 292 | return lp != 0; 293 | } 294 | 295 | /* Free objects in obstack H, including OBJ and everything allocate 296 | more recently than OBJ. If OBJ is zero, free everything in H. */ 297 | 298 | # undef obstack_free 299 | 300 | void 301 | obstack_free (struct obstack *h, void *obj) 302 | { 303 | register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ 304 | register struct _obstack_chunk *plp; /* point to previous chunk if any */ 305 | 306 | lp = h->chunk; 307 | /* We use >= because there cannot be an object at the beginning of a chunk. 308 | But there can be an empty object at that address 309 | at the end of another chunk. */ 310 | while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) 311 | { 312 | plp = lp->prev; 313 | CALL_FREEFUN (h, lp); 314 | lp = plp; 315 | /* If we switch chunks, we can't tell whether the new current 316 | chunk contains an empty object, so assume that it may. */ 317 | h->maybe_empty_object = 1; 318 | } 319 | if (lp) 320 | { 321 | h->object_base = h->next_free = (char *) (obj); 322 | h->chunk_limit = lp->limit; 323 | h->chunk = lp; 324 | } 325 | else if (obj != 0) 326 | /* obj is not in any of the chunks! */ 327 | abort (); 328 | } 329 | 330 | int 331 | _obstack_memory_used (struct obstack *h) 332 | { 333 | register struct _obstack_chunk* lp; 334 | register int nbytes = 0; 335 | 336 | for (lp = h->chunk; lp != 0; lp = lp->prev) 337 | { 338 | nbytes += lp->limit - (char *) lp; 339 | } 340 | return nbytes; 341 | } 342 | 343 | static void 344 | __attribute__ ((noreturn)) 345 | print_and_abort (void) 346 | { 347 | /* Don't change any of these strings. Yes, it would be possible to add 348 | the newline to the string and use fputs or so. But this must not 349 | happen because the "memory exhausted" message appears in other places 350 | like this and the translation should be reused instead of creating 351 | a very similar string which requires a separate translation. */ 352 | fprintf (stderr, "%s\n", "memory exhausted"); 353 | exit (obstack_exit_failure); 354 | } 355 | -------------------------------------------------------------------------------- /src-cpp/adt/obstack_printf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of cparser. 3 | * Copyright (C) 2007-2009 Matthias Braun 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 18 | * 02111-1307, USA. 19 | */ 20 | #include 21 | #include 22 | #include "obstack.h" 23 | 24 | int obstack_vprintf(struct obstack *obst, const char *fmt, va_list ap) 25 | { 26 | /* currently a poor implementation ... */ 27 | char buf[1024]; 28 | int len; 29 | 30 | len = vsnprintf(buf, sizeof(buf), fmt, ap); 31 | obstack_grow(obst, buf, len); 32 | 33 | return len; 34 | } 35 | 36 | int obstack_printf(struct obstack *obst, const char *fmt, ...) 37 | { 38 | va_list ap; 39 | int len; 40 | 41 | va_start(ap, fmt); 42 | len = obstack_vprintf(obst, fmt, ap); 43 | va_end(ap); 44 | 45 | return len; 46 | } 47 | -------------------------------------------------------------------------------- /src-cpp/adt/pdeq.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief double ended queue of generic pointers. 23 | * @author Christian von Roques 24 | * @date 1999 by getting from fiasco 25 | * @version $Id: pdeq.c 24125 2008-11-28 16:00:39Z mallon $ 26 | */ 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "fourcc.h" 33 | #include "pdeq.h" 34 | #include "xmalloc.h" 35 | #include "align.h" 36 | 37 | /* Pointer Double Ended Queue */ 38 | #define PDEQ_MAGIC1 FOURCC('P','D','E','1') 39 | #define PDEQ_MAGIC2 FOURCC('P','D','E','2') 40 | 41 | /** Size of pdeq block cache. */ 42 | #define TUNE_NSAVED_PDEQS 16 43 | 44 | /** 45 | * Maximal number of data items in a pdeq chunk. 46 | */ 47 | #define NDATA ((int)((PREF_MALLOC_SIZE - offsetof (pdeq, data)) / sizeof (void *))) 48 | 49 | #ifdef NDEBUG 50 | # define VRFY(dq) ((void)0) 51 | #else 52 | # define VRFY(dq) assert((dq) && ((dq)->magic == PDEQ_MAGIC1)) 53 | #endif 54 | 55 | /** 56 | * A pointer double ended queue. 57 | * This structure is used as a list chunk either. 58 | */ 59 | struct pdeq { 60 | #ifndef NDEBUG 61 | unsigned magic; /**< debug magic */ 62 | #endif 63 | pdeq *l_end, *r_end; /**< left and right ends of the queue */ 64 | pdeq *l, *r; /**< left and right neighbor */ 65 | int n; /**< number of elements in the current chunk */ 66 | int p; /**< the read/write pointer */ 67 | const void *data[1]; /**< storage for elements */ 68 | }; 69 | 70 | 71 | /** 72 | * cache of unused, pdeq blocks to speed up new_pdeq and del_pdeq. 73 | * +1 for compilers that can't grok empty arrays 74 | */ 75 | static pdeq *pdeq_block_cache[TUNE_NSAVED_PDEQS+1]; 76 | 77 | /** 78 | * Number of pdeqs in pdeq_store. 79 | */ 80 | static unsigned pdeqs_cached; 81 | 82 | /** 83 | * Free a pdeq chunk, put in into the cache if possible. 84 | * 85 | * @param p The pdeq chunk. 86 | */ 87 | static inline void free_pdeq_block (pdeq *p) 88 | { 89 | #ifndef NDEBUG 90 | p->magic = 0xbadf00d1; 91 | #endif 92 | if (pdeqs_cached < TUNE_NSAVED_PDEQS) { 93 | pdeq_block_cache[pdeqs_cached++] = p; 94 | } else { 95 | xfree (p); 96 | } 97 | } 98 | 99 | /** 100 | * Allocate a new pdeq chunk, get it from the cache if possible. 101 | * 102 | * @return A new pdeq chunk. 103 | */ 104 | static inline pdeq *alloc_pdeq_block (void) 105 | { 106 | pdeq *p; 107 | if (TUNE_NSAVED_PDEQS && pdeqs_cached) { 108 | p = pdeq_block_cache[--pdeqs_cached]; 109 | } else { 110 | p = xmalloc(PREF_MALLOC_SIZE); 111 | } 112 | return p; 113 | } 114 | 115 | 116 | #ifndef NDEBUG 117 | /** 118 | * Verify a double ended list, assert if failure. 119 | * 120 | * @param dq The list to verify. 121 | */ 122 | void _pdeq_vrfy(pdeq *dq) 123 | { 124 | pdeq *q; 125 | 126 | assert ( dq 127 | && (dq->magic == PDEQ_MAGIC1) 128 | && (dq->l_end && dq->r_end)); 129 | q = dq->l_end; 130 | while (q) { 131 | assert ( ((q == dq) || (q->magic == PDEQ_MAGIC2)) 132 | && ((q == dq->l_end) ^ (q->l != NULL)) 133 | && ((q == dq->r_end) ^ (q->r != NULL)) 134 | && (!q->l || (q == q->l->r)) 135 | && ((q->n >= 0) && (q->n <= NDATA)) 136 | && ((q == dq->l_end) || (q == dq->r_end) || (q->n == NDATA)) 137 | && ((q->p >= 0) && (q->p < NDATA))); 138 | q = q->r; 139 | } 140 | } 141 | #endif 142 | 143 | /* Creates a new double ended pointer list. */ 144 | pdeq *new_pdeq(void) 145 | { 146 | pdeq *dq; 147 | 148 | dq = alloc_pdeq_block(); 149 | 150 | #ifndef NDEBUG 151 | dq->magic = PDEQ_MAGIC1; 152 | #endif 153 | dq->l_end = dq->r_end = dq; 154 | dq->l = dq->r = NULL; 155 | dq->n = dq->p = 0; 156 | 157 | VRFY(dq); 158 | return dq; 159 | } 160 | 161 | /* Creates a new double ended pointer list and puts an initial pointer element in. */ 162 | pdeq *new_pdeq1(const void *x) 163 | { 164 | return pdeq_putr(new_pdeq(), x); 165 | } 166 | 167 | /* Delete a double ended pointer list. */ 168 | void del_pdeq(pdeq *dq) 169 | { 170 | pdeq *q, *qq; 171 | 172 | VRFY(dq); 173 | 174 | q = dq->l_end; /* left end of chain */ 175 | /* pdeq trunk empty, but !pdeq_empty() ==> trunk not in chain */ 176 | if (dq->n == 0 && dq->l_end != dq ) { 177 | free_pdeq_block(dq); 178 | } 179 | 180 | /* Free all blocks in the pdeq chain */ 181 | do { 182 | qq = q->r; 183 | free_pdeq_block(q); 184 | } while ((q = qq)); 185 | 186 | } 187 | 188 | /* Checks if a list is empty. */ 189 | int pdeq_empty(pdeq *dq) 190 | { 191 | VRFY(dq); 192 | return dq->l_end->n == 0; 193 | } 194 | 195 | /* Returns the length of a double ended pointer list. */ 196 | int pdeq_len(pdeq *dq) 197 | { 198 | int n; 199 | pdeq *q; 200 | 201 | VRFY(dq); 202 | 203 | n = 0; 204 | q = dq->l_end; 205 | do { 206 | n += q->n; 207 | q = q->r; 208 | } while (q); 209 | 210 | return n; 211 | } 212 | 213 | /* Add a pointer to the right site of a double ended pointer list. */ 214 | pdeq *pdeq_putr(pdeq *dq, const void *x) 215 | { 216 | pdeq *rdq; 217 | int n; 218 | 219 | VRFY(dq); 220 | 221 | rdq = dq->r_end; 222 | if (rdq->n >= NDATA) { /* tailblock full */ 223 | pdeq *ndq; 224 | 225 | ndq = dq; /* try to reuse trunk, but ... */ 226 | if (dq->n) { /* ... if trunk used */ 227 | /* allocate and init new block */ 228 | ndq = alloc_pdeq_block(); 229 | #ifndef NDEBUG 230 | ndq->magic = PDEQ_MAGIC2; 231 | #endif 232 | ndq->l_end = ndq->r_end = NULL; 233 | } 234 | 235 | ndq->r = NULL; 236 | ndq->l = rdq; rdq->r = ndq; 237 | ndq->n = 0; ndq->p = 0; 238 | dq->r_end = ndq; 239 | rdq = ndq; 240 | } 241 | 242 | n = rdq->n++ + rdq->p; 243 | if (n >= NDATA) n -= NDATA; 244 | 245 | rdq->data[n] = x; 246 | 247 | VRFY(dq); 248 | return dq; 249 | } 250 | 251 | /* Add a pointer to the left site of a double ended pointer list. */ 252 | pdeq *pdeq_putl(pdeq *dq, const void *x) 253 | { 254 | pdeq *ldq; 255 | int p; 256 | 257 | VRFY(dq); 258 | 259 | ldq = dq->l_end; 260 | if (ldq->n >= NDATA) { /* headblock full */ 261 | pdeq *ndq; 262 | 263 | ndq = dq; /* try to reuse trunk, but ... */ 264 | if (dq->n) { /* ... if trunk used */ 265 | /* allocate and init new block */ 266 | ndq = alloc_pdeq_block(); 267 | #ifndef NDEBUG 268 | ndq->magic = PDEQ_MAGIC2; 269 | #endif 270 | ndq->l_end = ndq->r_end = NULL; 271 | } 272 | 273 | ndq->l = NULL; 274 | ndq->r = ldq; ldq->l = ndq; 275 | ndq->n = 0; ndq->p = 0; 276 | dq->l_end = ndq; 277 | ldq = ndq; 278 | } 279 | 280 | ldq->n++; 281 | p = ldq->p - 1; 282 | if (p < 0) p += NDATA; 283 | ldq->p = p; 284 | 285 | ldq->data[p] = x; 286 | 287 | VRFY(dq); 288 | return dq; 289 | } 290 | 291 | /* Retrieve a pointer from the right site of a double ended pointer list. */ 292 | void *pdeq_getr(pdeq *dq) 293 | { 294 | pdeq *rdq; 295 | const void *x; 296 | int n; 297 | 298 | VRFY(dq); 299 | assert(dq->l_end->n); 300 | 301 | rdq = dq->r_end; 302 | n = rdq->p + --rdq->n; 303 | if (n >= NDATA) n -= NDATA; 304 | x = rdq->data[n]; 305 | 306 | if (rdq->n == 0) { 307 | if (rdq->l) { 308 | dq->r_end = rdq->l; 309 | rdq->l->r = NULL; 310 | rdq->l = NULL; 311 | } else { 312 | dq->r_end = dq->l_end = dq; 313 | } 314 | if (dq != rdq) { 315 | free_pdeq_block(rdq); 316 | } 317 | } 318 | 319 | VRFY(dq); 320 | return (void *)x; 321 | } 322 | 323 | /* Retrieve a pointer from the left site of a double ended pointer list. */ 324 | void *pdeq_getl(pdeq *dq) 325 | { 326 | pdeq *ldq; 327 | const void *x; 328 | int p; 329 | 330 | VRFY(dq); 331 | assert(dq->l_end->n); 332 | 333 | ldq = dq->l_end; 334 | p = ldq->p; 335 | x = ldq->data[p]; 336 | if (++p >= NDATA) p = 0; 337 | ldq->p = p; 338 | 339 | if (--ldq->n == 0) { 340 | if (ldq->r) { 341 | dq->l_end = ldq->r; 342 | ldq->r->l = NULL; 343 | ldq->r = NULL; 344 | } else { 345 | dq->l_end = dq->r_end = dq; 346 | } 347 | if (dq != ldq) { 348 | free_pdeq_block(ldq); 349 | } 350 | } 351 | 352 | VRFY(dq); 353 | return (void *)x; 354 | } 355 | 356 | /* 357 | * Returns non-zero if a double ended pointer list 358 | * contains a pointer x. 359 | */ 360 | int pdeq_contains(pdeq *dq, const void *x) 361 | { 362 | pdeq *q; 363 | 364 | VRFY(dq); 365 | 366 | q = dq->l_end; 367 | do { 368 | int p, ep; 369 | 370 | p = q->p; ep = p + q->n; 371 | 372 | if (ep > NDATA) { 373 | do { 374 | if (q->data[p] == x) return 1; 375 | } while (++p < NDATA); 376 | p = 0; 377 | ep -= NDATA; 378 | } 379 | 380 | while (p < ep) { 381 | if (q->data[p++] == x) return 1; 382 | } 383 | 384 | q = q->r; 385 | } while (q); 386 | 387 | return 0; 388 | } 389 | 390 | /* 391 | * Search a key in a double ended pointer list, the search 392 | * is controlled by a compare function. 393 | * An element is found, if the compare function returns 0. 394 | * The search is started from the left site of the list. 395 | */ 396 | void *pdeq_search(pdeq *dq, cmp_fun cmp, const void *key) 397 | { 398 | pdeq *q; 399 | int p; 400 | 401 | VRFY(dq); 402 | 403 | q = dq->l_end; 404 | do { 405 | int ep; 406 | 407 | p = q->p; ep = p + q->n; 408 | 409 | if (ep > NDATA) { 410 | do { 411 | if (!cmp (q->data[p], key)) return (void *)q->data[p-1]; 412 | } while (++p < NDATA); 413 | p = 0; 414 | ep -= NDATA; 415 | } 416 | 417 | while (p < ep) { 418 | if (!cmp (q->data[p++], key)) return (void *)q->data[p-1]; 419 | } 420 | 421 | q = q->r; 422 | } while (q); 423 | 424 | return NULL; 425 | } 426 | 427 | /* 428 | * Convert the double ended pointer list into a linear array beginning from 429 | * left, the first element in the linear array will be the left one. 430 | */ 431 | void **pdeq_copyl(pdeq *dq, const void **dst) 432 | { 433 | pdeq *q; 434 | const void **d = dst; 435 | 436 | VRFY(dq); 437 | 438 | q = dq->l_end; 439 | while (q) { 440 | int p, n; 441 | 442 | p = q->p; n = q->n; 443 | 444 | if (n + p > NDATA) { 445 | int nn = NDATA - p; 446 | memcpy((void *) d, &q->data[p], nn * sizeof(void *)); d += nn; 447 | p = 0; n -= nn; 448 | } 449 | 450 | memcpy((void *) d, &q->data[p], n * sizeof(void *)); d += n; 451 | 452 | q = q->r; 453 | } 454 | 455 | return (void **)dst; 456 | } 457 | 458 | /* 459 | * Convert the double ended pointer list into a linear array beginning from 460 | * right, the first element in the linear array will be the right one. 461 | */ 462 | void **pdeq_copyr(pdeq *dq, const void **dst) 463 | { 464 | pdeq *q; 465 | const void **d = dst; 466 | 467 | VRFY(dq); 468 | 469 | q = dq->r_end; 470 | while (q) { 471 | int p, i; 472 | 473 | p = q->p; i = q->n + p - 1; 474 | if (i >= NDATA) { 475 | i -= NDATA; 476 | do *d++ = q->data[i]; while (--i >= 0); 477 | i = NDATA - 1; 478 | } 479 | 480 | do *d++ = q->data[i]; while (--i >= p); 481 | 482 | q = q->l; 483 | } 484 | 485 | return (void **)dst; 486 | } 487 | -------------------------------------------------------------------------------- /src-cpp/adt/pdeq.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief double ended queue of generic pointers. 23 | * @author Christian von Roques 24 | * @version $Id: pdeq.h 26440 2009-08-28 09:26:27Z matze $ 25 | */ 26 | #ifndef FIRM_ADT_PDEQ_H 27 | #define FIRM_ADT_PDEQ_H 28 | 29 | /** 30 | * The type of the pointer compare function. 31 | * 32 | * @param elem The list element. 33 | * @param key The user supplied key. 34 | * 35 | * @return 0 if the element matches the key, non-zero else. 36 | */ 37 | typedef int (*cmp_fun)(const void *elem, const void *key); 38 | 39 | /** 40 | * The pointer double ended queue (list). 41 | */ 42 | typedef struct pdeq pdeq; 43 | 44 | /** 45 | * Creates a new double ended pointer list. 46 | * 47 | * @return A new list. 48 | */ 49 | pdeq *new_pdeq(void); 50 | 51 | /** 52 | * Creates a new double ended pointer list and puts an initial pointer element in. 53 | * 54 | * @param x The pointer element to put in. 55 | * 56 | * @return The new list. 57 | */ 58 | pdeq *new_pdeq1(const void *x); 59 | 60 | /** 61 | * Delete a double ended pointer list. 62 | * 63 | * @param dq The list to be deleted. 64 | */ 65 | void del_pdeq(pdeq *dq); 66 | 67 | /** 68 | * Returns the lenght of a double ended pointer list. 69 | * 70 | * @param dq The list. 71 | */ 72 | int pdeq_len(pdeq *dq); 73 | 74 | /** 75 | * Checks if a list is empty. 76 | * 77 | * @param dq The list. 78 | * 79 | * @return non-zero if the list is empty. 80 | */ 81 | int pdeq_empty(pdeq *dq); 82 | 83 | /** 84 | * Returns non-zero if a double ended pointer list 85 | * contains a pointer x. 86 | * 87 | * @param dq The list. 88 | * @param x The pointer to be searched for. 89 | */ 90 | int pdeq_contains(pdeq *dq, const void *x); 91 | 92 | /** 93 | * Search a key in a double ended pointer list, the search 94 | * is controlled by a compare function. 95 | * An element is found, if the compare function returns 0. 96 | * The search is started from the left site of the list. 97 | * 98 | * @param qp The list. 99 | * @param cmp The compare function. 100 | * @param key The search key. 101 | * 102 | * @return The address of the element entry if the key was found, 103 | * NULL else. 104 | */ 105 | void *pdeq_search(pdeq *qp, cmp_fun cmp, const void *key); 106 | 107 | /** 108 | * Convert the double ended pointer list into a linear array beginning from 109 | * left, the first element in the linear array will be the left one. 110 | * 111 | * @param qp The list. 112 | * @param dst A pointer to a pointer array with must be at least 113 | * pdeq_len(dq) * sizeof(void *) 114 | * 115 | * @return dst 116 | */ 117 | void **pdeq_copyl(pdeq *qp, const void **dst); 118 | 119 | /** 120 | * Convert the double ended pointer list into a linear array beginning from 121 | * right, the first element in the linear array will be the right one. 122 | * 123 | * @param qp The list. 124 | * @param dst A pointer to a pointer array with must be at least 125 | * pdeq_len(dq) * sizeof(void *) 126 | * 127 | * @return dst 128 | */ 129 | void **pdeq_copyr(pdeq *qp, const void **dst); 130 | 131 | /** 132 | * Add a pointer to the left side of a double ended pointer list. 133 | * 134 | * @param dq The list to add a pointer to. 135 | * @param x The pointer element to be added 136 | * 137 | * @return The list. 138 | */ 139 | pdeq *pdeq_putl(pdeq *dq, const void *x); 140 | 141 | /** 142 | * Add a pointer to the right side of a double ended pointer list. 143 | * 144 | * @param dq The list to add a pointer to. 145 | * @param x The pointer element to be added 146 | * 147 | * @return The list. 148 | */ 149 | pdeq *pdeq_putr(pdeq *dq, const void *x); 150 | 151 | /** 152 | * Retrieve (and remove) a pointer from the left site of a double ended pointer 153 | * list. 154 | * 155 | * @param dq The list 156 | * @return The pointer element. 157 | * @remark This function will fail if the list is empty. 158 | */ 159 | void *pdeq_getl(pdeq *dq); 160 | 161 | /** 162 | * Retrieve (and remove) a pointer from the right site of a double ended pointer 163 | * list. 164 | * 165 | * @param dq The list 166 | * @return The pointer element. 167 | * @remark This function will fail if the list is empty. 168 | */ 169 | void *pdeq_getr(pdeq *dq); 170 | 171 | #ifdef NDEBUG 172 | #define PDEQ_VRFY(deq) ((void)0) 173 | #else 174 | #define PDEQ_VRFY(deq) _pdeq_vrfy ((deq)) 175 | void _pdeq_vrfy(pdeq *dq); 176 | #endif 177 | 178 | /** 179 | * The pdeq is often used as a wait queue. A helper 180 | * type to support this. 181 | */ 182 | typedef pdeq waitq; 183 | 184 | /** 185 | * Creates a new pointer wait queue (fifo). 186 | * 187 | * @return A new queue. 188 | */ 189 | #define new_waitq() new_pdeq() 190 | 191 | /** 192 | * Delete a wait queue (fifo) 193 | * 194 | * @param wq The wait queue. 195 | */ 196 | #define del_waitq(wq) del_pdeq(wq) 197 | 198 | /** 199 | * Retrieve a pointer from the wait queue (fifo). 200 | * 201 | * @param wq The wait queue. 202 | * 203 | * @return The pointer element. 204 | * 205 | * @remark This function will fail if the queue is empty. 206 | */ 207 | #define waitq_get(wq) pdeq_getl(wq) 208 | 209 | /** 210 | * Add a pointer to the wait queue (fifo). 211 | * 212 | * @param wq The wait queue 213 | * @param x The pointer element to be added 214 | * 215 | * @return The wait queue. 216 | */ 217 | #define waitq_put(wq, x) pdeq_putr((wq), (x)) 218 | 219 | /** 220 | * Checks if a wait queue is empty. 221 | * 222 | * @param wq The wait queue. 223 | * 224 | * @return non-zero if the queue is empty. 225 | */ 226 | #define waitq_empty(wq) pdeq_empty(wq) 227 | 228 | /** 229 | * The pdeq can be used as a stack. A helper 230 | * type to support this. 231 | */ 232 | typedef pdeq stack; 233 | 234 | /** 235 | * Creates a new pointer stack (lifo). 236 | * 237 | * @return A new stack. 238 | */ 239 | #define new_stack() new_pdeq() 240 | 241 | /** 242 | * Pop a pointer from the stack (lifo). 243 | * 244 | * @param st The stack. 245 | * 246 | * @return The pointer element. 247 | * 248 | * @remark This function will fail if the stack is empty. 249 | */ 250 | #define stack_pop(st) pdeq_getr(st) 251 | 252 | /** 253 | * Push a pointer to the stack (lifo). 254 | * 255 | * @param st The stack. 256 | * @param x The pointer element to be added 257 | * 258 | * @return The stack. 259 | */ 260 | #define stack_push(st, x) pdeq_putr((st), (x)) 261 | 262 | /** 263 | * Checks if a stack is empty. 264 | * 265 | * @param st The stack. 266 | * 267 | * @return non-zero if the stack is empty. 268 | */ 269 | #define stack_empty(st) pdeq_empty(wq) 270 | 271 | #endif 272 | -------------------------------------------------------------------------------- /src-cpp/adt/pdeq.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libfirm/liboo/e4c221831da8fb29780cb17f0d4af0d83e05621f/src-cpp/adt/pdeq.o -------------------------------------------------------------------------------- /src-cpp/adt/raw_bitset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief helper functions for working with raw bitsets 23 | * @date 15.10.2004 24 | * @author Matthias Braun 25 | * @version $Id: raw_bitset.h 27155 2010-02-14 14:38:55Z mallon $ 26 | * @brief 27 | * Raw bitsets are constructed from unsigned int arrays. Additional information 28 | * like the size of the bitset or the used memory are not stored for 29 | * efficiency reasons. 30 | * 31 | * These bitsets need less space than bitset_t and their representation 32 | * as int arrays allows having constant bitsets in the ro data segment. 33 | * They should for smaller bitset, whose length is known through other means 34 | * (a typical usage case is a set of cpu registers) 35 | * 36 | * The bitset is built as an array of unsigned integers. It is assumed that 37 | * exactly 32 bits may be put into each element of the array. If there are 38 | * remaining bits, then they should be 0 39 | */ 40 | #ifndef FIRM_ADT_RAW_BITSET_H 41 | #define FIRM_ADT_RAW_BITSET_H 42 | 43 | #include 44 | #include "obst.h" 45 | 46 | /** The base type for raw bitsets. */ 47 | typedef unsigned int rawbs_base_t; 48 | 49 | #define BITS_PER_ELEM (sizeof(rawbs_base_t) * 8) 50 | #define BITSET_SIZE_ELEMS(size_bits) ((size_bits)/BITS_PER_ELEM + 1) 51 | #define BITSET_SIZE_BYTES(size_bits) (BITSET_SIZE_ELEMS(size_bits) * sizeof(rawbs_base_t)) 52 | #define BITSET_ELEM(bitset,pos) bitset[pos / BITS_PER_ELEM] 53 | 54 | /** 55 | * Allocate an empty raw bitset on the heap. 56 | * 57 | * @param size number of bits in the bitset 58 | * 59 | * @return the new bitset 60 | */ 61 | static inline unsigned *rbitset_malloc(unsigned size) { 62 | unsigned size_bytes = BITSET_SIZE_BYTES(size); 63 | unsigned *res = xmalloc(size_bytes); 64 | memset(res, 0, size_bytes); 65 | 66 | return res; 67 | } 68 | 69 | /** 70 | * Allocate an empty raw bitset on the stack. 71 | * 72 | * @param res will contain the newly allocated bitset 73 | * @param size number of bits in the bitset 74 | */ 75 | #define rbitset_alloca(res, size) \ 76 | do { \ 77 | unsigned size_bytes = BITSET_SIZE_BYTES(size); \ 78 | res = alloca(size_bytes); \ 79 | memset(res, 0, size_bytes); \ 80 | } while(0) 81 | 82 | /** 83 | * Allocate an empty raw bitset on an obstack. 84 | * 85 | * @param obst the obstack where the bitset is allocated on 86 | * @param size number of bits in the bitset 87 | * 88 | * @return the new bitset 89 | */ 90 | static inline unsigned *rbitset_obstack_alloc(struct obstack *obst, unsigned size) 91 | { 92 | unsigned size_bytes = BITSET_SIZE_BYTES(size); 93 | unsigned *res = obstack_alloc(obst, size_bytes); 94 | memset(res, 0, size_bytes); 95 | 96 | return res; 97 | } 98 | 99 | /** 100 | * Allocate an empty raw bitset including the size on an obstack. 101 | * The size of this bitset can be accessed by bitset[-1]. 102 | * 103 | * @param obst the obstack where the bitset is allocated on 104 | * @param size number of bits in the bitset 105 | * 106 | * @return the new bitset 107 | */ 108 | static inline unsigned *rbitset_w_size_obstack_alloc(struct obstack *obst, unsigned size) 109 | { 110 | unsigned size_bytes = BITSET_SIZE_BYTES(size); 111 | unsigned *res = obstack_alloc(obst, size_bytes + sizeof(unsigned)); 112 | *res = size; 113 | ++res; 114 | memset(res, 0, size_bytes); 115 | 116 | return res; 117 | } 118 | 119 | /** Return the size of a bitset allocated with a *_w_size_* function */ 120 | #define rbitset_size(set) (set)[-1] 121 | 122 | /** 123 | * Duplicate a raw bitset on an obstack. 124 | * 125 | * @param obst the obstack where the bitset is allocated on 126 | * @param old_bitset the bitset to be duplicated 127 | * @param size number of bits in the bitset 128 | * 129 | * @return the new bitset 130 | */ 131 | static inline unsigned *rbitset_duplicate_obstack_alloc(struct obstack *obst, 132 | const unsigned *old_bitset, unsigned size) 133 | { 134 | unsigned size_bytes = BITSET_SIZE_BYTES(size); 135 | unsigned *res = obstack_alloc(obst, size_bytes); 136 | memcpy(res, old_bitset, size_bytes); 137 | 138 | return res; 139 | } 140 | 141 | /** 142 | * Check if a bitset is empty, ie all bits cleared. 143 | */ 144 | static inline int rbitset_is_empty(unsigned *bitset, unsigned size) 145 | { 146 | unsigned n = BITSET_SIZE_ELEMS(size); 147 | unsigned i; 148 | for (i = 0; i < n; ++i) { 149 | if (bitset[i] != 0) 150 | return 0; 151 | } 152 | 153 | return 1; 154 | } 155 | 156 | /** 157 | * Set a bit at position pos. 158 | * 159 | * @param bitset the bitset 160 | * @param pos the position of the bit to be set 161 | */ 162 | static inline void rbitset_set(unsigned *bitset, unsigned pos) 163 | { 164 | BITSET_ELEM(bitset,pos) |= 1 << (pos % BITS_PER_ELEM); 165 | } 166 | 167 | /** 168 | * Set all bits in a given bitset. 169 | * 170 | * @param bitset the bitset 171 | * @param size number of bits in the bitset 172 | */ 173 | static inline void rbitset_set_all(unsigned *bitset, unsigned size) 174 | { 175 | unsigned size_bytes = BITSET_SIZE_BYTES(size); 176 | memset(bitset, ~0, size_bytes); 177 | } 178 | 179 | 180 | /** 181 | * Clear a bit at position pos. 182 | * 183 | * @param bitset the bitset 184 | * @param pos the position of the bit to be clear 185 | */ 186 | static inline void rbitset_clear(unsigned *bitset, unsigned pos) 187 | { 188 | BITSET_ELEM(bitset, pos) &= ~(1 << (pos % BITS_PER_ELEM)); 189 | } 190 | 191 | /** 192 | * Clear all bits in a given bitset. 193 | * 194 | * @param bitset the bitset 195 | * @param size number of bits in the bitset 196 | */ 197 | static inline void rbitset_clear_all(unsigned *bitset, unsigned size) 198 | { 199 | unsigned size_bytes = BITSET_SIZE_BYTES(size); 200 | memset(bitset, 0, size_bytes); 201 | } 202 | 203 | /** 204 | * Check if a bit is set at position pos. 205 | * 206 | * @param bitset the bitset 207 | * @param pos the position of the bit to check 208 | */ 209 | static inline int rbitset_is_set(const unsigned *bitset, unsigned pos) 210 | { 211 | return BITSET_ELEM(bitset, pos) & (1 << (pos % BITS_PER_ELEM)); 212 | } 213 | 214 | /** 215 | * Inplace Intersection of two sets. 216 | * 217 | * @param dst the destination bitset and first operand 218 | * @param src the second bitset 219 | * @param size size of both bitsets 220 | */ 221 | static inline void rbitset_and(unsigned *dst, const unsigned *src, unsigned size) 222 | { 223 | unsigned i, n = BITSET_SIZE_ELEMS(size); 224 | 225 | for (i = 0; i < n; ++i) { 226 | dst[i] &= src[i]; 227 | } 228 | } 229 | 230 | /** 231 | * Inplace Union of two sets. 232 | * 233 | * @param dst the destination bitset and first operand 234 | * @param src the second bitset 235 | * @param size size of both bitsets 236 | */ 237 | static inline void rbitset_or(unsigned *dst, const unsigned *src, unsigned size) 238 | { 239 | unsigned i, n = BITSET_SIZE_ELEMS(size); 240 | 241 | for (i = 0; i < n; ++i) { 242 | dst[i] |= src[i]; 243 | } 244 | } 245 | 246 | /** 247 | * Remove all bits in src from dst. 248 | * 249 | * @param dst the destination bitset and first operand 250 | * @param src the second bitset 251 | * @param size size of both bitsets 252 | */ 253 | static inline void rbitset_andnot(unsigned *dst, const unsigned *src, unsigned size) 254 | { 255 | unsigned i, n = BITSET_SIZE_ELEMS(size); 256 | 257 | for (i = 0; i < n; ++i) { 258 | dst[i] &= ~src[i]; 259 | } 260 | } 261 | 262 | /** 263 | * Xor of two bitsets. 264 | * 265 | * @param dst the destination bitset and first operand 266 | * @param src the second bitset 267 | * @param size size of both bitsets 268 | */ 269 | static inline void rbitset_xor(unsigned *dst, const unsigned *src, unsigned size) 270 | { 271 | unsigned i, n = BITSET_SIZE_ELEMS(size); 272 | 273 | for (i = 0; i < n; ++i) { 274 | dst[i] ^= src[i]; 275 | } 276 | } 277 | 278 | /** 279 | * Returns 1 of two bitsets are equal. 280 | * 281 | * @param bitset1 the first bitset 282 | * @param bitset2 the second bitset 283 | * @param size size of both bitsets 284 | */ 285 | static inline int rbitset_equal(const unsigned *bitset1, 286 | const unsigned *bitset2, size_t size) 287 | { 288 | return memcmp(bitset1, bitset2, BITSET_SIZE_BYTES(size)) == 0; 289 | } 290 | 291 | /** 292 | * Tests wether 2 bitsets wether at least 1 bit is set in both. 293 | * 294 | * @param bitset1 the first bitset 295 | * @param bitset2 the second bitset 296 | * @param size size of both bitsets 297 | */ 298 | static inline int rbitsets_have_common(const unsigned *bitset1, 299 | const unsigned *bitset2, size_t size) 300 | { 301 | unsigned i; 302 | unsigned n = BITSET_SIZE_ELEMS(size); 303 | 304 | for (i = 0; i < n; ++i) { 305 | if ((bitset1[i] & bitset2[i]) != 0) 306 | return 1; 307 | } 308 | return 0; 309 | } 310 | 311 | /** 312 | * Copy a raw bitset into another. 313 | * 314 | * @param dst the destination set 315 | * @param src the source set 316 | * @param size size of both bitsets 317 | */ 318 | static inline void rbitset_copy(unsigned *dst, const unsigned *src, size_t size) 319 | { 320 | memcpy(dst, src, BITSET_SIZE_BYTES(size)); 321 | } 322 | 323 | #endif 324 | -------------------------------------------------------------------------------- /src-cpp/adt/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of libFirm. 3 | * Copyright (C) 2012 University of Karlsruhe. 4 | */ 5 | 6 | /** 7 | * @file 8 | * @date 31.05.2005 9 | * @author Sebastian Hack 10 | * @brief Miscellaneous utility macros. 11 | */ 12 | #ifndef FIRM_ADT_UTIL_H 13 | #define FIRM_ADT_UTIL_H 14 | 15 | #include 16 | 17 | /** 18 | * Make pointer to the struct from a pointer to a member of that struct. 19 | * @param ptr The pointer to the member. 20 | * @param type The type of the struct. 21 | * @param member The name of the member. 22 | * @return A pointer to the struct member is in. 23 | */ 24 | #define firm_container_of(ptr, type, member) \ 25 | ((type *) ((char *) (ptr) - offsetof(type, member))) 26 | 27 | /** 28 | * Returns size of a static array. Warning: This returns invalid values for 29 | * dynamically allocated arrays. 30 | * 31 | * @param a static array 32 | */ 33 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 34 | 35 | #undef MIN 36 | #undef MAX 37 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) 38 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) 39 | 40 | /** 41 | * Three valued compare as demanded by e.g. qsort(3) 42 | * @param c A number. 43 | * @param d Another number. 44 | * @return 0 if c == d, -1 if c < d, 1 if c > d. 45 | */ 46 | #define QSORT_CMP(c, d) (((c) > (d)) - ((c) < (d))) 47 | 48 | /** 49 | * convert an integer into pointer 50 | */ 51 | #define INT_TO_PTR(v) ((void *)((char *)0 + (v))) 52 | 53 | /** 54 | * convert a pointer into an integer 55 | */ 56 | #define PTR_TO_INT(v) (((char *)(v) - (char *)0)) 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src-cpp/adt/xmalloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. 3 | * 4 | * This file is part of libFirm. 5 | * 6 | * This file may be distributed and/or modified under the terms of the 7 | * GNU General Public License version 2 as published by the Free Software 8 | * Foundation and appearing in the file LICENSE.GPL included in the 9 | * packaging of this file. 10 | * 11 | * Licensees holding valid libFirm Professional Edition licenses may use 12 | * this file in accordance with the libFirm Commercial License. 13 | * Agreement provided with the Software. 14 | * 15 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 16 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE. 18 | */ 19 | 20 | /** 21 | * @file 22 | * @brief never failing wrappers for malloc() & friends. 23 | * @author Markus Armbruster 24 | * @version $Id: xmalloc.h 26728 2009-11-19 13:21:05Z matze $ 25 | * @note The functions here never fail because they simply abort your 26 | * program in case of an error. 27 | */ 28 | #ifndef FIRM_ADT_XMALLOC_H 29 | #define FIRM_ADT_XMALLOC_H 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | /* xmalloc() & friends. */ 40 | 41 | void *xmalloc(size_t size); 42 | void *xrealloc(void *ptr, size_t size); 43 | char *xstrdup(const char *str); 44 | 45 | #define xfree(ptr) free(ptr) 46 | 47 | /** 48 | * Allocate n objects of a certain type 49 | */ 50 | #define XMALLOCN(type, n) ((type*)xmalloc(sizeof(type) * (n))) 51 | 52 | /** 53 | * Allocate n objects of a certain type and zero them 54 | */ 55 | #define XMALLOCNZ(type, n) ((type*)memset(xmalloc(sizeof(type) * (n)), 0, sizeof(type) * (n))) 56 | 57 | /** 58 | * Allocate one object of a certain type 59 | */ 60 | #define XMALLOC(type) XMALLOCN(type, 1) 61 | 62 | /** 63 | * Allocate one object of a certain type and zero it 64 | */ 65 | #define XMALLOCZ(type) XMALLOCNZ(type, 1) 66 | 67 | /** 68 | * Reallocate n objects of a certain type 69 | */ 70 | #define XREALLOC(ptr, type, n) ((type*)xrealloc(ptr, sizeof(type) * (n))) 71 | 72 | /** 73 | * Allocate an object with n elements of a flexible array member 74 | */ 75 | #define XMALLOCF(type, member, n) ((type*)xmalloc(offsetof(type, member) + sizeof(*((type*)0)->member) * (n))) 76 | 77 | /** 78 | * Allocate an object with n elements of a flexible array member and zero the 79 | * whole object 80 | */ 81 | #define XMALLOCFZ(type, member, n) ((type*)memset(XMALLOCF(type, member, (n)), 0, offsetof(type, member) + sizeof(*((type*)0)->member) * (n))) 82 | 83 | /** 84 | * Allocate n objects of a certain type on the stack 85 | */ 86 | #define ALLOCAN(type, n) ((type*)alloca(sizeof(type) * (n))) 87 | 88 | /** 89 | * Allocate n objects of a certain type on the stack and zero them 90 | */ 91 | #define ALLOCANZ(type, n) ((type*)memset((type*)alloca(sizeof(type) * (n)), 0, sizeof(type) * (n))) 92 | 93 | /** 94 | * Allocate n objects of a certain type on the given obstack 95 | */ 96 | #define OALLOCN(obst, type, n) ((type*)obstack_alloc((obst), sizeof(type) * (n))) 97 | 98 | /** 99 | * Allocate n objects of a certain type on the given obstack and zero them 100 | */ 101 | #define OALLOCNZ(obst, type, n) ((type*)memset(OALLOCN((obst), type, (n)), 0, sizeof(type) * (n))) 102 | 103 | /** 104 | * Allocate one object of a certain type on the given obstack 105 | */ 106 | #define OALLOC(obst, type) OALLOCN(obst, type, 1) 107 | 108 | /** 109 | * Allocate one object of a certain type on the given obstack and zero it 110 | */ 111 | #define OALLOCZ(obst, type) OALLOCNZ(obst, type, 1) 112 | 113 | /** 114 | * Allocate an object with n elements of a flexible array member on the given 115 | * obstck 116 | */ 117 | #define OALLOCF(obst, type, member, n) ((type*)obstack_alloc((obst), offsetof(type, member) + sizeof(*((type*)0)->member) * (n))) 118 | 119 | /** 120 | * Allocate an object with n elements of a flexible array member on the given 121 | * obstack and zero the whole object 122 | */ 123 | #define OALLOCFZ(obst, type, member, n) ((type*)memset(OALLOCF((obst), type, member, (n)), 0, offsetof(type, member) + sizeof(*((type*)0)->member) * (n))) 124 | 125 | 126 | /* Includes for alloca() */ 127 | #ifdef _WIN32 128 | #include 129 | #endif 130 | #ifdef HAVE_ALLOCA_H 131 | #include 132 | #endif 133 | 134 | #ifdef __cplusplus 135 | } 136 | #endif 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /src-cpp/debuginfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include "liboo/debuginfo.h" 6 | #include "adt/obst.h" 7 | #include "adt/error.h" 8 | #include "adt/xmalloc.h" 9 | 10 | typedef struct debuginfo_t { 11 | ident *filename; 12 | uint32_t line; 13 | uint16_t column; 14 | uint16_t length; 15 | } debuginfo_t; 16 | 17 | static struct obstack obst; 18 | 19 | static src_loc_t dbg_retrieve(const dbg_info *dbg) 20 | { 21 | const debuginfo_t *info = (const debuginfo_t*) dbg; 22 | src_loc_t loc = { NULL, 0, 0 }; 23 | if (info == NULL) 24 | return loc; 25 | loc.file = get_id_str(info->filename); 26 | loc.line = info->line; 27 | loc.column = info->column; 28 | return loc; 29 | } 30 | 31 | void debuginfo_init(void) 32 | { 33 | obstack_init(&obst); 34 | ir_set_debug_retrieve(dbg_retrieve); 35 | } 36 | 37 | void debuginfo_deinit(void) 38 | { 39 | obstack_free(&obst, NULL); 40 | } 41 | 42 | const dbg_info *create_debuginfo(ident *filename, unsigned line, 43 | unsigned column, unsigned length) 44 | { 45 | debuginfo_t *info = OALLOC(&obst, debuginfo_t); 46 | info->filename = filename; 47 | info->line = (uint32_t) line; 48 | info->column = (uint16_t) column; 49 | info->length = (uint16_t) length; 50 | return (const dbg_info*) info; 51 | } 52 | -------------------------------------------------------------------------------- /src-cpp/dmemory.c: -------------------------------------------------------------------------------- 1 | #include "liboo/dmemory.h" 2 | #include "liboo/nodes.h" 3 | 4 | #include 5 | #include "liboo/ddispatch.h" 6 | #include "liboo/oo.h" 7 | #include "adt/error.h" 8 | #include "adt/util.h" 9 | 10 | struct dmemory_model_t { 11 | get_arraylength_t get_arraylength; 12 | } dmemory_model; 13 | 14 | static ir_mode *default_arraylength_mode; 15 | 16 | ir_node *dmemory_default_get_arraylength(dbg_info *dbgi, ir_node *block, 17 | ir_node *objptr, ir_node **mem) 18 | { 19 | /* calculate address of arraylength field */ 20 | ir_graph *irg = get_irn_irg(block); 21 | int length_len = get_mode_size_bytes(default_arraylength_mode); 22 | ir_node *cnst = new_r_Const_long(irg, mode_P, -length_len); 23 | ir_node *length_addr = new_rd_Add(dbgi, block, objptr, cnst); 24 | 25 | ir_node *cur_mem = *mem; 26 | ir_type *length_type = get_type_for_mode(default_arraylength_mode); 27 | ir_node *load = new_rd_Load(dbgi, block, cur_mem, length_addr, default_arraylength_mode, length_type, cons_none); 28 | cur_mem = new_r_Proj(load, mode_M, pn_Load_M); 29 | ir_node *len = new_r_Proj(load, default_arraylength_mode, pn_Load_res); 30 | *mem = cur_mem; 31 | return len; 32 | } 33 | 34 | void dmemory_init(void) 35 | { 36 | default_arraylength_mode = mode_Is; 37 | dmemory_model.get_arraylength = dmemory_default_get_arraylength; 38 | } 39 | 40 | void dmemory_lower_Arraylength(ir_node *arraylength) 41 | { 42 | dbg_info *dbgi = get_irn_dbg_info(arraylength); 43 | ir_node *array_ref = get_Arraylength_ptr(arraylength); 44 | ir_node *block = get_nodes_block(arraylength); 45 | ir_node *cur_mem = get_Arraylength_mem(arraylength); 46 | ir_node *len = (*dmemory_model.get_arraylength)(dbgi, block, array_ref, &cur_mem); 47 | 48 | ir_node *in[pn_Arraylength_max+1] = { 49 | [pn_Arraylength_M] = cur_mem, 50 | [pn_Arraylength_res] = len 51 | }; 52 | turn_into_tuple(arraylength, ARRAY_SIZE(in), in); 53 | } 54 | 55 | void dmemory_set_allocation_methods(get_arraylength_t ga_func) 56 | { 57 | assert(ga_func); 58 | dmemory_model.get_arraylength = ga_func; 59 | } 60 | -------------------------------------------------------------------------------- /src-cpp/eh.c: -------------------------------------------------------------------------------- 1 | #include "liboo/eh.h" 2 | #include "liboo/nodes.h" 3 | #include "adt/error.h" 4 | #include "adt/obst.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef LIBOO_EXCEPTION_SUPPORT 11 | 12 | struct _lpad_t; 13 | typedef struct _lpad_t lpad_t; 14 | struct _lpad_t { 15 | ir_node *handler_header_block; 16 | ir_node *cur_block; 17 | ir_node *exception_object; 18 | bool used; 19 | lpad_t *prev; 20 | }; 21 | 22 | static struct obstack lpads; 23 | static lpad_t *top; 24 | 25 | static ir_entity *exception_object_entity; 26 | static ir_entity *throw_entity; 27 | 28 | ir_node *eh_get_exception_object(void) 29 | { 30 | ir_node *cur_mem = get_store(); 31 | 32 | ir_node *ex_symc = new_Address(exception_object_entity); 33 | ir_node *ex_load = new_Load(cur_mem, ex_symc, mode_P, cons_none); 34 | cur_mem = new_Proj(ex_load, mode_M, pn_Load_M); 35 | ir_node *ex_obj = new_Proj(ex_load, mode_P, pn_Load_res); 36 | 37 | set_store(cur_mem); 38 | return ex_obj; 39 | } 40 | 41 | static void store_exception_object(ir_node *exo_ptr) 42 | { 43 | ir_node *cur_mem = get_store(); 44 | 45 | ir_node *ex_symc = new_Address(exception_object_entity); 46 | ir_node *ex_store = new_Store(cur_mem, ex_symc, exo_ptr, cons_none); 47 | cur_mem = new_Proj(ex_store, mode_M, pn_Store_M); 48 | 49 | set_store(cur_mem); 50 | } 51 | 52 | void eh_init(void) 53 | { 54 | obstack_init(&lpads); 55 | ir_type *type_reference = new_type_primitive(mode_P); 56 | exception_object_entity = new_entity(get_tls_type(), new_id_from_str("__oo_rt_exception_object__"), type_reference); 57 | set_entity_initializer(exception_object_entity, get_initializer_null()); 58 | 59 | ir_type *throw_type = new_type_method(1, 0); 60 | set_method_param_type(throw_type, 0, type_reference); 61 | throw_entity = new_entity(get_glob_type(), new_id_from_str("firm_personality"), throw_type); 62 | set_entity_visibility(throw_entity, ir_visibility_external); 63 | 64 | top = NULL; 65 | } 66 | 67 | void eh_deinit(void) 68 | { 69 | obstack_free(&lpads, NULL); 70 | } 71 | 72 | void eh_start_method(void) 73 | { 74 | assert (irg_is_constrained(get_current_ir_graph(), IR_GRAPH_CONSTRAINT_CONSTRUCTION)); 75 | assert (obstack_object_size(&lpads) == 0); 76 | eh_new_lpad(); 77 | } 78 | 79 | void eh_new_lpad(void) 80 | { 81 | lpad_t *new_pad = (lpad_t*) obstack_alloc(&lpads, sizeof(lpad_t)); 82 | new_pad->handler_header_block = new_immBlock(); 83 | new_pad->cur_block = new_pad->handler_header_block; 84 | new_pad->exception_object = NULL; 85 | new_pad->used = false; 86 | new_pad->prev = top; 87 | 88 | top = new_pad; 89 | 90 | ir_node *saved_block = get_cur_block(); 91 | set_cur_block(new_pad->cur_block); 92 | 93 | top->exception_object = eh_get_exception_object(); 94 | 95 | set_cur_block(saved_block); 96 | } 97 | 98 | void eh_add_handler(ir_type *catch_type, ir_node *catch_block) 99 | { 100 | assert (top->prev); //e.g., not the default handler 101 | assert (top->cur_block && "Cannot add handler after an catch all was registered"); 102 | 103 | ir_node *saved_block = get_cur_block(); 104 | set_cur_block(top->cur_block); 105 | 106 | if (catch_type) { 107 | ir_node *cur_mem = get_store(); 108 | ir_node *instanceof = new_InstanceOf(cur_mem, top->exception_object, catch_type); 109 | cur_mem = new_Proj(instanceof, mode_M, pn_InstanceOf_M); 110 | ir_node *result = new_Proj(instanceof, mode_b, pn_InstanceOf_res); 111 | ir_node *cond = new_Cond(result); 112 | 113 | ir_node *proj_match = new_Proj(cond, mode_X, pn_Cond_true); 114 | add_immBlock_pred(catch_block, proj_match); 115 | // will be matured elsewhere 116 | 117 | ir_node *proj_go_on = new_Proj(cond, mode_X, pn_Cond_false); 118 | ir_node *new_block = new_immBlock(); 119 | add_immBlock_pred(new_block, proj_go_on); 120 | mature_immBlock(new_block); 121 | top->cur_block = new_block; 122 | set_store(cur_mem); 123 | } else { 124 | ir_node *jmp = new_Jmp(); 125 | add_immBlock_pred(catch_block, jmp); 126 | top->cur_block = NULL; 127 | } 128 | 129 | set_cur_block(saved_block); 130 | } 131 | 132 | ir_node *eh_new_Call(ir_node * irn_ptr, int arity, ir_node *const * in, ir_type* type) 133 | { 134 | ir_node *jmp = new_Jmp(); 135 | ir_node *call_block = new_immBlock(); 136 | add_immBlock_pred(call_block, jmp); 137 | mature_immBlock(call_block); 138 | set_cur_block(call_block); 139 | 140 | ir_node *cur_mem = get_store(); 141 | ir_node *call = new_Call(cur_mem, irn_ptr, arity, in, type); 142 | ir_set_throws_exception(call, 1); 143 | ir_node *proj_except = new_Proj(call, mode_X, pn_Call_X_except); 144 | cur_mem = new_Proj(call, mode_M, pn_Call_M); 145 | set_store(cur_mem); 146 | 147 | add_immBlock_pred(top->handler_header_block, proj_except); 148 | 149 | ir_node *proj_regular = new_Proj(call, mode_X, pn_Call_X_regular); 150 | ir_node *new_block = new_immBlock(); 151 | add_immBlock_pred(new_block, proj_regular); 152 | mature_immBlock(new_block); 153 | set_cur_block(new_block); 154 | 155 | top->used = true; 156 | 157 | return call; 158 | } 159 | 160 | void eh_throw(ir_node *exo_ptr) 161 | { 162 | store_exception_object(exo_ptr); 163 | 164 | ir_node *throw = new_Jmp(); 165 | 166 | add_immBlock_pred(top->handler_header_block, throw); 167 | top->used = true; 168 | set_cur_block(NULL); 169 | } 170 | 171 | void eh_pop_lpad(void) 172 | { 173 | mature_immBlock(top->handler_header_block); 174 | 175 | //assert (top->used && "No exception is ever thrown"); 176 | 177 | lpad_t *prev = top->prev; 178 | assert (prev); 179 | 180 | if (top->cur_block) { 181 | // the popped lpad didn't have a catch all handler and therefore is still "open". 182 | ir_node *saved_block = get_cur_block(); 183 | set_cur_block(top->cur_block); 184 | 185 | ir_node *jmp = new_Jmp(); 186 | add_immBlock_pred(prev->handler_header_block, jmp); 187 | 188 | set_cur_block(saved_block); 189 | } 190 | 191 | obstack_free(&lpads, top); 192 | top = prev; 193 | } 194 | 195 | void eh_end_method(void) 196 | { 197 | assert (! top->prev); // the explicit stuff is gone, we have the default handler 198 | 199 | if (top->used) { 200 | mature_immBlock(top->handler_header_block); 201 | 202 | assert (top->cur_block); // would fail if front end adds an catch all handler to the default handler 203 | 204 | ir_node *saved_block = get_cur_block(); 205 | set_cur_block(top->cur_block); 206 | ir_node *cur_mem = get_store(); 207 | ir_node *raise = new_Raise(cur_mem, top->exception_object); 208 | ir_node *proj = new_Proj(raise, mode_X, pn_Raise_X); 209 | cur_mem = new_Proj(raise, mode_M, pn_Raise_M); 210 | set_store(cur_mem); 211 | 212 | ir_node *end_block = get_irg_end_block(get_current_ir_graph()); 213 | add_immBlock_pred(end_block, proj); 214 | 215 | set_cur_block(saved_block); 216 | } 217 | 218 | obstack_free(&lpads, top); 219 | top = NULL; 220 | } 221 | 222 | void eh_lower_Raise(ir_node *raise, ir_node *proj) 223 | { 224 | assert (is_Raise(raise) && is_Proj(proj)); 225 | 226 | ir_node *ex_obj = get_Raise_exo_ptr(raise); 227 | ir_node *block = get_nodes_block(raise); 228 | ir_graph *irg = get_irn_irg(raise); 229 | ir_node *cur_mem = get_Raise_mem(raise); 230 | 231 | ir_node *c_symc = new_r_SymConst(irg, throw_entity); 232 | ir_node *in[1] = { ex_obj }; 233 | 234 | ir_node *throw = new_r_Call(block, cur_mem, c_symc, 1, in, get_entity_type(throw_entity)); 235 | ir_set_throws_exception(throw, 1); 236 | exchange(raise, throw); 237 | set_Proj_num(proj, pn_Call_X_except); 238 | } 239 | 240 | #else 241 | 242 | ir_node *eh_get_exception_object(void) 243 | { 244 | panic("liboo compiled without exception support"); 245 | } 246 | 247 | void eh_init(void) 248 | { 249 | } 250 | 251 | void eh_deinit(void) 252 | { 253 | } 254 | 255 | void eh_start_method(void) 256 | { 257 | panic("liboo compiled without exception support"); 258 | } 259 | 260 | void eh_new_lpad(void) 261 | { 262 | panic("liboo compiled without exception support"); 263 | } 264 | 265 | void eh_add_handler(ir_type *catch_type, ir_node *catch_block) 266 | { 267 | (void)catch_type; 268 | (void)catch_block; 269 | panic("liboo compiled without exception support"); 270 | } 271 | 272 | ir_node *eh_new_Call(ir_node * irn_ptr, int arity, ir_node *const * in, ir_type* type) 273 | { 274 | (void)irn_ptr; 275 | (void)arity; 276 | (void)in; 277 | (void)type; 278 | panic("liboo compiled without exception support"); 279 | } 280 | 281 | void eh_throw(ir_node *exo_ptr) 282 | { 283 | (void)exo_ptr; 284 | panic("liboo compiled without exception support"); 285 | } 286 | 287 | void eh_pop_lpad(void) 288 | { 289 | panic("liboo compiled without exception support"); 290 | } 291 | 292 | void eh_end_method(void) 293 | { 294 | panic("liboo compiled without exception support"); 295 | } 296 | 297 | void eh_lower_Raise(ir_node *raise, ir_node *proj) 298 | { 299 | (void)raise; 300 | (void)proj; 301 | panic("liboo compiled without exception support"); 302 | } 303 | #endif 304 | -------------------------------------------------------------------------------- /src-cpp/nodes_attr.h: -------------------------------------------------------------------------------- 1 | #ifndef OO_NODES_ATTR_H 2 | #define OO_NODES_ATTR_H 3 | 4 | #include 5 | 6 | typedef struct op_InstanceOf_attr_t { 7 | ir_type *type; 8 | } op_InstanceOf_attr_t; 9 | 10 | typedef struct op_MethodSel_attr_t { 11 | ir_entity *entity; 12 | } op_MethodSel_attr_t; 13 | 14 | typedef struct op_VptrIsSet_attr_t { 15 | ir_type *type; 16 | } op_VptrIsSet_attr_t; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src-cpp/oo.c: -------------------------------------------------------------------------------- 1 | #include "liboo/oo.h" 2 | 3 | #include 4 | #include "liboo/rtti.h" 5 | #include "liboo/dmemory.h" 6 | #include "liboo/nodes.h" 7 | #include "liboo/eh.h" 8 | #include "adt/obst.h" 9 | #include "libfirm/adt/pmap.h" 10 | #include "adt/error.h" 11 | #include "gen_irnode.h" 12 | 13 | typedef enum { 14 | oo_is_abstract = 1 << 0, 15 | oo_is_final = 1 << 1, 16 | oo_is_interface = 1 << 2, 17 | oo_is_inherited = 1 << 3, 18 | oo_is_extern = 1 << 4, 19 | oo_is_transient = 1 << 5 20 | } oo_info_flags; 21 | 22 | typedef enum { 23 | k_oo_BAD = k_ir_max+1, 24 | k_oo_type_info, 25 | k_oo_entity_info, 26 | k_oo_node_info, 27 | } oo_info_kind; 28 | 29 | typedef struct { 30 | oo_info_kind kind; 31 | unsigned uid; 32 | ir_entity *vptr; 33 | ir_entity *rtti; 34 | ir_entity *itt; 35 | ir_entity *vtable; 36 | unsigned vtable_size; 37 | unsigned flags; 38 | void *link; 39 | } oo_type_info; 40 | 41 | typedef struct { 42 | oo_info_kind kind; 43 | bool exclude_from_vtable; 44 | int vtable_index; 45 | unsigned flags; 46 | ddispatch_binding binding; 47 | void *link; 48 | } oo_entity_info; 49 | 50 | typedef struct { 51 | oo_info_kind kind; 52 | bool bind_statically; 53 | } oo_node_info; 54 | 55 | static struct obstack oo_info_obst; 56 | static pmap *oo_node_info_map = NULL; 57 | 58 | static ddispatch_interface_call interface_call_type; 59 | 60 | static oo_type_info *get_type_info(ir_type *type) 61 | { 62 | oo_type_info *ti = (oo_type_info*) get_type_link(type); 63 | if (ti == NULL) { 64 | ti = (oo_type_info*) obstack_alloc(&oo_info_obst, sizeof(oo_type_info)); 65 | memset(ti, 0, sizeof(*ti)); 66 | ti->kind = k_oo_type_info; 67 | set_type_link(type, ti); 68 | } else { 69 | assert(ti->kind == k_oo_type_info); 70 | } 71 | return ti; 72 | } 73 | 74 | static oo_entity_info *get_entity_info(ir_entity *entity) 75 | { 76 | oo_entity_info *ei = (oo_entity_info*) get_entity_link(entity); 77 | if (ei == NULL) { 78 | ei = (oo_entity_info*) obstack_alloc(&oo_info_obst, sizeof(oo_entity_info)); 79 | memset(ei, 0, sizeof(*ei)); 80 | ei->kind = k_oo_entity_info; 81 | ei->vtable_index = -1; 82 | set_entity_link(entity, ei); 83 | } else { 84 | assert(ei->kind == k_oo_entity_info); 85 | } 86 | return ei; 87 | } 88 | 89 | static oo_node_info *get_node_info(ir_node *node) 90 | { 91 | oo_node_info *ni = pmap_get(oo_node_info, oo_node_info_map, node); 92 | if (ni == NULL) { 93 | ni = (oo_node_info*) obstack_alloc(&oo_info_obst, sizeof(oo_node_info)); 94 | memset(ni, 0, sizeof(*ni)); 95 | ni->kind = k_oo_node_info; 96 | ni->bind_statically = false; 97 | pmap_insert(oo_node_info_map, node, ni); 98 | } else { 99 | assert(ni->kind == k_oo_node_info); 100 | } 101 | return ni; 102 | } 103 | 104 | unsigned oo_get_class_uid(ir_type *classtype) 105 | { 106 | assert(is_Class_type(classtype)); 107 | oo_type_info *ti = get_type_info(classtype); 108 | return ti->uid; 109 | } 110 | 111 | void oo_set_class_uid(ir_type *classtype, unsigned uid) 112 | { 113 | assert(is_Class_type(classtype)); 114 | oo_type_info *ti = get_type_info(classtype); 115 | ti->uid = uid; 116 | } 117 | 118 | ir_entity *oo_get_class_vtable_entity(ir_type *classtype) 119 | { 120 | assert(is_Class_type(classtype)); 121 | oo_type_info *ti = get_type_info(classtype); 122 | return ti->vtable; 123 | } 124 | 125 | void oo_set_class_vtable_entity(ir_type *classtype, ir_entity *vtable) 126 | { 127 | assert(is_Class_type(classtype)); 128 | oo_type_info *ti = get_type_info(classtype); 129 | ti->vtable = vtable; 130 | } 131 | 132 | unsigned oo_get_class_vtable_size(ir_type *classtype) 133 | { 134 | assert(is_Class_type(classtype)); 135 | oo_type_info *ti = get_type_info(classtype); 136 | 137 | return ti->vtable_size; 138 | } 139 | void oo_set_class_vtable_size(ir_type *classtype, unsigned vtable_size) 140 | { 141 | assert(is_Class_type(classtype)); 142 | oo_type_info *ti = get_type_info(classtype); 143 | ti->vtable_size = vtable_size; 144 | } 145 | 146 | ir_entity *oo_get_class_vptr_entity(ir_type *classtype) 147 | { 148 | assert(is_Class_type(classtype)); 149 | oo_type_info *ti = get_type_info(classtype); 150 | if (ti->vptr != NULL) 151 | return ti->vptr; 152 | 153 | /* recursively search for vptr entity in supertypes */ 154 | int n_supertypes = get_class_n_supertypes(classtype); 155 | for (int i = 0; i < n_supertypes; ++i) { 156 | ir_type *supertype = get_class_supertype(classtype, i); 157 | ti = get_type_info(supertype); 158 | if (ti->vptr != NULL) 159 | return ti->vptr; 160 | } 161 | return NULL; 162 | } 163 | 164 | void oo_set_class_vptr_entity(ir_type *classtype, ir_entity *vptr) 165 | { 166 | assert(is_Class_type(classtype)); 167 | oo_type_info *ti = get_type_info(classtype); 168 | ti->vptr = vptr; 169 | } 170 | 171 | ir_entity *oo_get_class_rtti_entity(ir_type *classtype) 172 | { 173 | assert(is_Class_type(classtype)); 174 | oo_type_info *ti = get_type_info(classtype); 175 | return ti->rtti; 176 | } 177 | 178 | void oo_set_class_rtti_entity(ir_type *classtype, ir_entity *rtti) 179 | { 180 | assert(is_Class_type(classtype)); 181 | oo_type_info *ti = get_type_info(classtype); 182 | ti->rtti = rtti; 183 | } 184 | 185 | ir_entity *oo_get_class_itt_entity(ir_type *classtype) 186 | { 187 | assert(is_Class_type(classtype)); 188 | oo_type_info *ti = get_type_info(classtype); 189 | return ti->itt; 190 | } 191 | 192 | void oo_set_class_itt_entity(ir_type *classtype, ir_entity *itt) 193 | { 194 | assert(is_Class_type(classtype)); 195 | oo_type_info *ti = get_type_info(classtype); 196 | ti->itt = itt; 197 | } 198 | 199 | bool oo_get_class_is_interface(ir_type *classtype) 200 | { 201 | assert(is_Class_type(classtype)); 202 | oo_type_info *ti = get_type_info(classtype); 203 | return ti->flags & oo_is_interface; 204 | } 205 | 206 | void oo_set_class_is_interface(ir_type *classtype, bool is_interface) 207 | { 208 | assert(is_Class_type(classtype)); 209 | oo_type_info *ti = get_type_info(classtype); 210 | if (is_interface) 211 | ti->flags |= oo_is_interface; 212 | else 213 | ti->flags &= ~oo_is_interface; 214 | } 215 | 216 | bool oo_get_class_is_abstract(ir_type *classtype) 217 | { 218 | assert(is_Class_type(classtype)); 219 | oo_type_info *ti = get_type_info(classtype); 220 | return ti->flags & oo_is_abstract; 221 | } 222 | 223 | void oo_set_class_is_abstract(ir_type *classtype, bool is_abstract) 224 | { 225 | assert(is_Class_type(classtype)); 226 | oo_type_info *ti = get_type_info(classtype); 227 | if (is_abstract) 228 | ti->flags |= oo_is_abstract; 229 | else 230 | ti->flags &= ~oo_is_abstract; 231 | } 232 | 233 | bool oo_get_class_is_final(ir_type *classtype) 234 | { 235 | assert(is_Class_type(classtype)); 236 | oo_type_info *ti = get_type_info(classtype); 237 | return ti->flags & oo_is_final; 238 | } 239 | 240 | void oo_set_class_is_final(ir_type *classtype, bool is_final) 241 | { 242 | assert(is_Class_type(classtype)); 243 | oo_type_info *ti = get_type_info(classtype); 244 | if (is_final) 245 | ti->flags |= oo_is_final; 246 | else 247 | ti->flags &= ~oo_is_final; 248 | } 249 | 250 | bool oo_get_class_is_extern(ir_type *classtype) 251 | { 252 | assert(is_Class_type(classtype)); 253 | oo_type_info *ti = get_type_info(classtype); 254 | 255 | return ti->flags & oo_is_extern; 256 | } 257 | void oo_set_class_is_extern(ir_type *classtype, bool is_extern) 258 | { 259 | assert(is_Class_type(classtype)); 260 | oo_type_info *ti = get_type_info(classtype); 261 | if (is_extern) 262 | ti->flags |= oo_is_extern; 263 | else 264 | ti->flags &= ~oo_is_extern; 265 | 266 | } 267 | 268 | void *oo_get_type_link(ir_type *type) 269 | { 270 | oo_type_info *ti = get_type_info(type); 271 | return ti->link; 272 | } 273 | 274 | void oo_set_type_link(ir_type *type, void* link) 275 | { 276 | oo_type_info *ti = get_type_info(type); 277 | ti->link = link; 278 | } 279 | 280 | bool oo_get_method_exclude_from_vtable(ir_entity *method) 281 | { 282 | assert(is_method_entity(method)); 283 | oo_entity_info *ei = get_entity_info(method); 284 | return ei->exclude_from_vtable; 285 | } 286 | 287 | void oo_set_method_exclude_from_vtable(ir_entity *method, bool exclude_from_vtable) 288 | { 289 | assert(is_method_entity(method)); 290 | oo_entity_info *ei = get_entity_info(method); 291 | ei->exclude_from_vtable = exclude_from_vtable; 292 | } 293 | 294 | int oo_get_method_vtable_index(ir_entity *method) 295 | { 296 | assert(is_method_entity(method)); 297 | oo_entity_info *ei = get_entity_info(method); 298 | return ei->vtable_index; 299 | } 300 | 301 | void oo_set_method_vtable_index(ir_entity *method, int vtable_index) 302 | { 303 | assert(is_method_entity(method)); 304 | oo_entity_info *ei = get_entity_info(method); 305 | ei->vtable_index = vtable_index; 306 | } 307 | 308 | bool oo_get_method_is_abstract(ir_entity *method) 309 | { 310 | assert(is_method_entity(method)); 311 | oo_entity_info *ei = get_entity_info(method); 312 | return ei->flags & oo_is_abstract; 313 | } 314 | 315 | void oo_set_method_is_abstract(ir_entity *method, bool is_abstract) 316 | { 317 | assert(is_method_entity(method)); 318 | oo_entity_info *ei = get_entity_info(method); 319 | if (is_abstract) 320 | ei->flags |= oo_is_abstract; 321 | else 322 | ei->flags &= ~oo_is_abstract; 323 | } 324 | 325 | bool oo_get_method_is_final(ir_entity *method) 326 | { 327 | assert(is_method_entity(method)); 328 | oo_entity_info *ei = get_entity_info(method); 329 | return ei->flags & oo_is_final; 330 | } 331 | 332 | void oo_set_method_is_final(ir_entity *method, bool is_final) 333 | { 334 | assert(is_method_entity(method)); 335 | oo_entity_info *ei = get_entity_info(method); 336 | if (is_final) 337 | ei->flags |= oo_is_final; 338 | else 339 | ei->flags &= ~oo_is_final; 340 | } 341 | 342 | bool oo_get_method_is_inherited(ir_entity *method) 343 | { 344 | assert(is_method_entity(method)); 345 | oo_entity_info *ei = get_entity_info(method); 346 | return ei->flags & oo_is_inherited; 347 | } 348 | 349 | void oo_set_method_is_inherited(ir_entity *method, bool is_inherited) 350 | { 351 | assert(is_method_entity(method)); 352 | oo_entity_info *ei = get_entity_info(method); 353 | if (is_inherited) 354 | ei->flags |= oo_is_inherited; 355 | else 356 | ei->flags &= ~oo_is_inherited; 357 | } 358 | 359 | bool oo_get_field_is_transient(ir_entity *field) 360 | { 361 | assert(!is_method_entity(field)); 362 | oo_entity_info *ei = get_entity_info(field); 363 | return ei->flags & oo_is_transient; 364 | } 365 | 366 | void oo_set_field_is_transient(ir_entity *field, bool is_transient) 367 | { 368 | assert(!is_method_entity(field)); 369 | oo_entity_info *ei = get_entity_info(field); 370 | if (is_transient) 371 | ei->flags |= oo_is_transient; 372 | else 373 | ei->flags &= ~oo_is_transient; 374 | } 375 | 376 | ddispatch_binding oo_get_entity_binding(ir_entity *entity) 377 | { 378 | oo_entity_info *ei = get_entity_info(entity); 379 | return ei->binding; 380 | } 381 | 382 | void oo_set_entity_binding(ir_entity *entity, ddispatch_binding binding) 383 | { 384 | oo_entity_info *ei = get_entity_info(entity); 385 | ei->binding = binding; 386 | } 387 | 388 | void oo_set_call_is_statically_bound(ir_node *call, bool bind_statically) 389 | { 390 | assert(is_Call(call)); 391 | oo_node_info *ni = get_node_info(call); 392 | ni->bind_statically = bind_statically; 393 | } 394 | 395 | bool oo_get_call_is_statically_bound(ir_node *call) 396 | { 397 | assert(is_Call(call)); 398 | 399 | /* Shortcut to avoid creating a node_info for each call we see. 400 | * Nearly all calls are bound just like their referenced method 401 | * entity specifies, and just very few (like super.method() in 402 | * Java) must be handled specially. */ 403 | if (!pmap_contains(oo_node_info_map, call)) 404 | return false; 405 | 406 | oo_node_info *ni = get_node_info(call); 407 | return ni->bind_statically; 408 | } 409 | 410 | void *oo_get_entity_link(ir_entity *entity) 411 | { 412 | oo_entity_info *ei = get_entity_info(entity); 413 | return ei->link; 414 | } 415 | 416 | void oo_set_entity_link(ir_entity *entity, void* link) 417 | { 418 | oo_entity_info *ei = get_entity_info(entity); 419 | ei->link = link; 420 | } 421 | 422 | // Filter out supertypes that are interfaces and return the first real superclass. 423 | ir_type *oo_get_class_superclass(ir_type *klass) 424 | { 425 | assert(is_Class_type(klass)); 426 | 427 | ir_type *superclass = NULL; 428 | size_t n_supertyes = get_class_n_supertypes(klass); 429 | for (size_t s = 0; s < n_supertyes; s++) { 430 | ir_type *st = get_class_supertype(klass, s); 431 | if (oo_get_class_is_interface(st)) 432 | continue; 433 | 434 | assert(!superclass && "multiple inheritance unsupported"); 435 | 436 | superclass = st; 437 | } 438 | return superclass; 439 | } 440 | 441 | // Filter out the overwritten entites that belong to interfaces. 442 | ir_entity *oo_get_entity_overwritten_superclass_entity(ir_entity *entity) 443 | { 444 | assert(is_method_entity(entity)); 445 | 446 | ir_entity *superclass_entity = NULL; 447 | size_t n_overwrites = get_entity_n_overwrites(entity); 448 | for (size_t s = 0; s < n_overwrites; s++) { 449 | ir_entity *se = get_entity_overwrites(entity, s); 450 | ir_type *owner = get_entity_owner(se); 451 | assert(owner != get_glob_type()); 452 | if (oo_get_class_is_interface(owner)) 453 | continue; 454 | 455 | assert(!superclass_entity && "multiple inheritance unsupported"); 456 | 457 | superclass_entity = se; 458 | } 459 | return superclass_entity; 460 | } 461 | 462 | void oo_copy_entity_info(ir_entity *src, ir_entity *dest) 463 | { 464 | oo_entity_info *ei_src = get_entity_info(src); 465 | oo_entity_info *ei_dest = get_entity_info(dest); 466 | memcpy(ei_dest, ei_src, sizeof(oo_entity_info)); 467 | } 468 | 469 | static void setup_itable_proxy(ir_type *klass, void *env) 470 | { 471 | (void)env; 472 | ddispatch_setup_itable(klass); 473 | } 474 | 475 | 476 | static void setup_vtable_proxy(ir_type *klass, void *env) 477 | { 478 | (void)env; 479 | ddispatch_setup_vtable(klass); 480 | } 481 | 482 | static void construct_runtime_typeinfo_proxy(ir_type *klass, void *env) 483 | { 484 | (void)env; 485 | rtti_construct_runtime_typeinfo(klass); 486 | } 487 | 488 | static void lower_node(ir_node *node, void *env) 489 | { 490 | (void)env; 491 | if (is_Call(node)) { 492 | ddispatch_lower_Call(node); 493 | } else if (is_Arraylength(node)) { 494 | dmemory_lower_Arraylength(node); 495 | } else if (is_InstanceOf(node)) { 496 | rtti_lower_InstanceOf(node); 497 | } else if (is_Proj(node)) { 498 | ir_node *pred = get_Proj_pred(node); 499 | if (is_Raise(pred) && get_Proj_num(node) == pn_Raise_X) { 500 | eh_lower_Raise(pred, node); 501 | } else if (is_VptrIsSet(pred)) { 502 | unsigned pn = get_Proj_num(node); 503 | switch ((pn_VptrIsSet)pn) { 504 | case pn_VptrIsSet_M: 505 | exchange(node, get_VptrIsSet_mem(pred)); 506 | return; 507 | case pn_VptrIsSet_res: 508 | exchange(node, get_VptrIsSet_ptr(pred)); 509 | return; 510 | } 511 | panic("invalid VptrIsSet Proj"); 512 | } 513 | } 514 | } 515 | 516 | static void lower_type(ir_type *type, void *env) 517 | { 518 | (void)env; 519 | assert(is_Class_type(type)); 520 | 521 | ir_type *glob = get_glob_type(); 522 | if (type == glob) 523 | return; 524 | 525 | int n_members = get_class_n_members(type); 526 | for (int m = n_members-1; m >= 0; m--) { 527 | ir_entity *entity = get_class_member(type, m); 528 | if (!is_method_entity(entity)) 529 | continue; 530 | ident *ld_name = get_entity_ld_ident(entity); 531 | ir_entity *ge = ir_get_global(ld_name); 532 | if (NULL != ge) { 533 | /* There is already an entity in global with this name. 534 | * Assume that it is actually the same. 535 | * 536 | * We need this behavior for x10i, because there is no Object class, 537 | * where every class derives from and which owns methods like 538 | * hashCode. Instead there is an Any interface at the top and 539 | * interfaces cannot own methods. This skipping should happen 540 | * exactly for the Any methods. 541 | */ 542 | remove_compound_member(type, entity); // TODO free_entity? 543 | } else { 544 | set_entity_owner(entity, glob); 545 | } 546 | /* When changing the entity owner type, the overwrites 547 | * information becomes nonsensical and invalid. */ 548 | const size_t n_overwrites = get_entity_n_overwrites(entity); 549 | for (size_t i = 0; i < n_overwrites; ++i) { 550 | ir_entity *over = get_entity_overwrites(entity, 0); 551 | remove_entity_overwrites(entity, over); 552 | } 553 | } 554 | } 555 | 556 | void oo_set_interface_call_type(ddispatch_interface_call type) 557 | { 558 | interface_call_type = type; 559 | } 560 | 561 | ddispatch_interface_call oo_get_interface_call_type() 562 | { 563 | return interface_call_type; 564 | } 565 | 566 | void oo_init(void) 567 | { 568 | obstack_init(&oo_info_obst); 569 | oo_node_info_map = pmap_create(); 570 | oo_init_opcodes(); 571 | ddispatch_init(); 572 | dmemory_init(); 573 | rtti_init(); 574 | eh_init(); 575 | } 576 | 577 | void oo_deinit(void) 578 | { 579 | rtti_deinit(); 580 | ddispatch_deinit(); 581 | eh_deinit(); 582 | obstack_free(&oo_info_obst, NULL); 583 | pmap_destroy(oo_node_info_map); 584 | } 585 | 586 | void oo_lower(void) 587 | { 588 | 589 | ddispatch_interface_call call_type = oo_get_interface_call_type(); 590 | if ((call_type & call_searched_itable) == call_searched_itable || 591 | call_type == call_itable_indexed) { 592 | class_walk_super2sub(setup_itable_proxy, NULL, NULL); 593 | } 594 | 595 | class_walk_super2sub(setup_vtable_proxy, NULL, NULL); 596 | class_walk_super2sub(construct_runtime_typeinfo_proxy, NULL, NULL); 597 | 598 | int n_irgs = get_irp_n_irgs(); 599 | for (int i = 0; i < n_irgs; ++i) { 600 | ir_graph *irg = get_irp_irg(i); 601 | irg_walk_graph(irg, NULL, lower_node, NULL); 602 | } 603 | 604 | class_walk_super2sub(lower_type, NULL, NULL); 605 | } 606 | -------------------------------------------------------------------------------- /src-cpp/opt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "adt/util.h" 10 | #include "liboo/nodes.h" 11 | #include "liboo/opt.h" 12 | 13 | static bool is_subtype(ir_type *test, ir_type *type) 14 | { 15 | if (test == type) 16 | return true; 17 | for (size_t i = 0, n = get_class_n_supertypes(test); i < n; ++i) { 18 | ir_type *super = get_class_supertype(test, i); 19 | if (is_subtype(super, type)) 20 | return true; 21 | } 22 | return false; 23 | } 24 | 25 | static ir_node *transform_node_InstanceOf(ir_node *node) 26 | { 27 | bool result; 28 | ir_node *ptr = get_InstanceOf_ptr(node); 29 | // The null-pointer is not an instance of anything 30 | if (is_Const(ptr) && tarval_is_null(get_Const_tarval(ptr))) { 31 | result = false; 32 | goto make_tuple; 33 | } 34 | 35 | /* if we have a VptrIsSet as predecessor then we can evaluate the 36 | * instanceof right away */ 37 | if (!is_Proj(ptr)) 38 | return node; 39 | ir_node *pred = get_Proj_pred(ptr); 40 | if (!is_VptrIsSet(pred)) 41 | return node; 42 | 43 | ir_type *tested = get_InstanceOf_type(node); 44 | ir_type *actual = get_VptrIsSet_type(pred); 45 | result = is_subtype(actual, tested); 46 | 47 | make_tuple:; 48 | ir_graph *irg = get_irn_irg(node); 49 | ir_node *res = new_r_Const(irg, result ? tarval_b_true : tarval_b_false); 50 | ir_node *tuple_in[] = { 51 | [pn_InstanceOf_M] = get_InstanceOf_mem(node), 52 | [pn_InstanceOf_res] = res, 53 | }; 54 | ir_node *block = get_nodes_block(node); 55 | return new_r_Tuple(block, ARRAY_SIZE(tuple_in), tuple_in); 56 | } 57 | 58 | void oo_register_opt_funcs(void) 59 | { 60 | set_op_transform_node(op_InstanceOf, transform_node_InstanceOf); 61 | } 62 | -------------------------------------------------------------------------------- /src-cpp/rt/error_functions.c: -------------------------------------------------------------------------------- 1 | #include "../adt/error.h" 2 | #include "rt.h" 3 | 4 | void oo_rt_abstract_method_error(void) 5 | { 6 | panic("Cannot invoke abstract method."); 7 | } 8 | -------------------------------------------------------------------------------- /src-cpp/rt/exceptions.c: -------------------------------------------------------------------------------- 1 | #ifdef LIBOO_EXCEPTION_SUPPORT 2 | #define UNW_LOCAL_ONLY 3 | /* Workaround for buggy glibcs. */ 4 | #define _BSD_SOURCE 5 | #include 6 | #undef _BSD_SOURCE 7 | 8 | #include "liboo/rts_types.h" 9 | #include 10 | #include 11 | #include 12 | 13 | extern void firm_personality(void *exception_object); 14 | 15 | extern __thread void *__oo_rt_exception_object__; 16 | 17 | static void oo_rt_unwind(void) 18 | { 19 | unw_cursor_t cursor; unw_context_t uc; 20 | unw_word_t ip; 21 | unw_proc_info_t pi; 22 | 23 | unw_getcontext(&uc); 24 | unw_init_local(&cursor, &uc); 25 | 26 | while (unw_step(&cursor) > 0) { 27 | unw_get_reg(&cursor, UNW_REG_IP, &ip); 28 | unw_get_proc_info(&cursor, &pi); 29 | 30 | if (pi.lsda != 0 && (void (*)(void*))pi.handler == firm_personality) { 31 | lsda_t *lsda = (lsda_t*) pi.lsda; 32 | for (unsigned i = 0; i < lsda->n_entries; i++) { 33 | if (ip == (unsigned)lsda->entries[i].ip) { 34 | unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)lsda->entries[i].handler); 35 | unw_resume(&cursor); 36 | } 37 | } 38 | } 39 | } 40 | } 41 | 42 | __attribute__ ((unused)) 43 | void firm_personality(void *exception_object) 44 | { 45 | __oo_rt_exception_object__ = exception_object; 46 | oo_rt_unwind(); 47 | 48 | fprintf(stderr, "UNCAUGHT EXCEPTION 0x%p\n", exception_object); 49 | abort(); 50 | } 51 | #else 52 | extern void liboo_dummy_func(void); 53 | void liboo_dummy_func(void) 54 | { 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /src-cpp/rt/instanceof.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../adt/error.h" 3 | #include "rt.h" 4 | 5 | bool oo_rt_instanceof(const class_info_t *objclass, 6 | const class_info_t *refclass) 7 | { 8 | if (objclass == refclass) 9 | return true; 10 | 11 | if (objclass->superclass && oo_rt_instanceof(objclass->superclass, refclass)) 12 | return true; 13 | 14 | if (objclass->n_interfaces > 0) { 15 | for (uint32_t i = 0; i < objclass->n_interfaces; i++) { 16 | class_info_t *ci = objclass->interfaces[i]; 17 | if (oo_rt_instanceof(ci, refclass)) 18 | return true; 19 | } 20 | } 21 | 22 | return false; 23 | } 24 | -------------------------------------------------------------------------------- /src-cpp/rt/interface_lookup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "liboo/rts_types.h" 3 | #include "../adt/error.h" 4 | #include "rt.h" 5 | #include "types.h" 6 | 7 | #define ITT_MOVE2FRONT_AREA 5 8 | 9 | void *oo_rt_lookup_interface_method(const class_info_t *klass, 10 | const string_const_t *method_name) 11 | { 12 | const class_info_t *k = klass; 13 | do { 14 | for (uint32_t i = 0; i < k->n_methods; i++) { 15 | const method_info_t *method = &k->methods[i]; 16 | if (string_const_equals(method->name, method_name)) { 17 | return method->funcptr; 18 | } 19 | } 20 | // not found, try the superclass 21 | k = k->superclass; 22 | } while (k != NULL); 23 | 24 | panic("Interface lookup for %s in %s failed", get_string_const_chars(method_name), get_string_const_chars(klass->name)); 25 | } 26 | 27 | void *oo_searched_itable_method_m2f(const object_t *obj, void *interface_id, int32_t offset) 28 | { 29 | itt_entry_t *itt = obj->vptr->itt; 30 | 31 | int32_t i = itt[0].next; 32 | 33 | int32_t counter = 1; 34 | do { 35 | if (itt[i].id == interface_id) { 36 | void *method = itt[i].itable[offset]; 37 | 38 | if (counter > ITT_MOVE2FRONT_AREA) { 39 | if (itt[i].prev > 0) 40 | itt[itt[i].prev].next = itt[i].next; 41 | if (itt[i].next > 0) 42 | itt[itt[i].next].prev = itt[i].prev; 43 | 44 | itt[itt[0].next].prev = i; 45 | itt[i].next = itt[0].next; 46 | 47 | itt[0].next = i; 48 | itt[i].prev = 0; 49 | } 50 | 51 | return method; 52 | } 53 | counter++; 54 | } 55 | while ((i = itt[i].next) > 0); 56 | 57 | panic("itable not found"); 58 | } 59 | 60 | void *oo_searched_itable_method(const object_t *obj, void *interface_id, int32_t offset) 61 | { 62 | itt_entry_t *itt = obj->vptr->itt; 63 | 64 | int32_t i = 1; 65 | 66 | int32_t counter = 1; 67 | do { 68 | if (itt[i].id == interface_id) { 69 | return itt[i].itable[offset]; 70 | } 71 | counter++; 72 | } 73 | while (itt[++i].id != NULL); 74 | 75 | panic("itable not found"); 76 | } 77 | -------------------------------------------------------------------------------- /src-cpp/rt/rt.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBOO_RT_H 2 | #define LIBOO_RT_H 3 | 4 | #include 5 | #include "liboo/rts_types.h" 6 | #include "types.h" 7 | 8 | /* declarations for runtime interface. (Though most users probably won't use 9 | * this from a C-Compiler... */ 10 | 11 | void oo_rt_abstract_method_error(void); 12 | bool oo_rt_instanceof(const class_info_t *objclass, 13 | const class_info_t *refclass); 14 | void *oo_rt_lookup_interface_method(const class_info_t *klass, 15 | const string_const_t *method_name); 16 | void *oo_searched_itable_method(const object_t *obj, void *interface_id, 17 | int32_t offset); 18 | void *oo_searched_itable_method_m2f(const object_t *obj, void *interface_id, 19 | int32_t offset); 20 | #endif 21 | -------------------------------------------------------------------------------- /src-cpp/rt/types.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_H 2 | #define TYPES_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct rtti_t { 9 | void *dummy; 10 | }; 11 | typedef struct rtti_t rtti_t; 12 | 13 | struct itt_entry_t { 14 | void **itable; 15 | void *id; 16 | int32_t prev; 17 | int32_t next; 18 | }; 19 | typedef struct itt_entry_t itt_entry_t; 20 | 21 | struct vtable_t { 22 | rtti_t *rtti; 23 | itt_entry_t *itt; 24 | void *dynamic_methods[]; 25 | }; 26 | typedef struct vtable_t vtable_t; 27 | 28 | struct object_t { 29 | vtable_t *vptr; 30 | }; 31 | typedef struct object_t object_t; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/firm/DebugInfo.java: -------------------------------------------------------------------------------- 1 | package firm; 2 | 3 | import com.sun.jna.Native; 4 | import com.sun.jna.Pointer; 5 | 6 | public class DebugInfo { 7 | static { Native.register("oo"); } 8 | public static native void debuginfo_init(); 9 | public static native void debuginfo_deinit(); 10 | public static native Pointer create_debuginfo(Pointer filename_ident, 11 | int line, int column, 12 | int length); 13 | } -------------------------------------------------------------------------------- /src/firm/OO.java: -------------------------------------------------------------------------------- 1 | package firm; 2 | 3 | import com.sun.jna.Pointer; 4 | 5 | import firm.bindings.binding_oo; 6 | import firm.nodes.Node; 7 | import firm.oo.nodes.Nodes; 8 | 9 | /** 10 | * Object-Orientation helper library API 11 | */ 12 | public final class OO { 13 | private static boolean initialized; 14 | 15 | public enum InterfaceCallType { 16 | RUNTIME_LOOKUP, 17 | SEARCHED_ITABLE, 18 | INDEXED_ITABLE, 19 | SEARCHED_ITABLE_M2F 20 | } 21 | 22 | private OO() { 23 | } 24 | 25 | /** 26 | * initializes OO library. Must be called once before using any other 27 | * functions from this class. 28 | */ 29 | public static void init() { 30 | assert initialized == false; /* we may only use 1 OO object at once... */ 31 | binding_oo.oo_init(); 32 | Nodes.init(); 33 | initialized = true; 34 | } 35 | 36 | /** 37 | * deinitializes OO library. This frees some allocated resources 38 | */ 39 | public static void deinit() { 40 | binding_oo.oo_deinit(); 41 | initialized = false; 42 | } 43 | 44 | /** 45 | * Lower Object-Oriented constructs into low-level stuff 46 | */ 47 | public static void lowerProgram() { 48 | binding_oo.oo_lower(); 49 | } 50 | 51 | /** 52 | * Sets the call-type for interface methods 53 | * @param callType 54 | */ 55 | public static void setInterfaceLookup(InterfaceCallType callType) { 56 | if (callType == InterfaceCallType.RUNTIME_LOOKUP) 57 | binding_oo.oo_set_interface_call_type(0); 58 | else if (callType == InterfaceCallType.SEARCHED_ITABLE) 59 | binding_oo.oo_set_interface_call_type(1); 60 | else if (callType == InterfaceCallType.INDEXED_ITABLE) 61 | binding_oo.oo_set_interface_call_type(2); 62 | else if (callType == InterfaceCallType.SEARCHED_ITABLE_M2F) 63 | binding_oo.oo_set_interface_call_type(1 | 4); 64 | } 65 | 66 | /** 67 | * lets you configure which methods should be included in the vtable 68 | */ 69 | public static void setMethodExcludeFromVTable(Entity entity, boolean includeInVTable) { 70 | binding_oo.oo_set_method_exclude_from_vtable(entity.ptr, includeInVTable); 71 | } 72 | 73 | /** 74 | * lets you mark a method as abstract 75 | */ 76 | public static void setMethodAbstract(Entity entity, boolean isAbstract) { 77 | binding_oo.oo_set_method_is_abstract(entity.ptr, isAbstract); 78 | } 79 | 80 | /** 81 | * @return true if method is abstract 82 | */ 83 | public static boolean isMethodAbstract(Entity entity) { 84 | return binding_oo.oo_get_method_is_abstract(entity.ptr); 85 | } 86 | 87 | public static void setMethodIsFinal(Entity entity, boolean isFinal) { 88 | binding_oo.oo_set_method_is_final(entity.ptr, isFinal); 89 | } 90 | 91 | public static boolean getMethodIsFinal(Entity entity) { 92 | return binding_oo.oo_get_method_is_final(entity.ptr); 93 | } 94 | 95 | public static void setMethodIsInherited(Entity entity, boolean isInherited) { 96 | binding_oo.oo_set_method_is_inherited(entity.ptr, isInherited); 97 | } 98 | 99 | /** 100 | * @return true if the given field is transient 101 | */ 102 | public static boolean getFieldIsTransient(Entity entity) { 103 | return binding_oo.oo_get_field_is_transient(entity.ptr); 104 | } 105 | 106 | /** 107 | * lets you mark a method as transient 108 | */ 109 | public static void setFieldIsTransient(Entity entity, boolean isTransient) { 110 | binding_oo.oo_set_field_is_transient(entity.ptr, isTransient); 111 | } 112 | 113 | /** 114 | * lets you specify the binding mode of a method 115 | */ 116 | public static void setEntityBinding(Entity entity, binding_oo.ddispatch_binding binding) { 117 | binding_oo.oo_set_entity_binding(entity.ptr, binding.val); 118 | } 119 | 120 | /** 121 | * returns the binding mode of a method 122 | */ 123 | public static binding_oo.ddispatch_binding getEntityBinding(Entity entity) { 124 | int binding = binding_oo.oo_get_entity_binding(entity.ptr); 125 | return binding_oo.ddispatch_binding.getEnum(binding); 126 | } 127 | 128 | /** 129 | * Lets you specify static binding for a single call. 130 | * This overwrites any possibly different binding information in the 131 | * method entity referenced by the call. 132 | */ 133 | public static void setCallIsStaticallyBound(Node call, boolean isStaticallyBound) { 134 | binding_oo.oo_set_call_is_statically_bound(call.ptr, isStaticallyBound); 135 | } 136 | 137 | /** 138 | * @return the unique compile time type id for the given class type. 139 | */ 140 | public static int getClassUID(ClassType classType) { 141 | return binding_oo.oo_get_class_uid(classType.ptr); 142 | } 143 | 144 | /** 145 | * Sets the the unique compile time type id for the given class type. 146 | */ 147 | public static void setClassUID(ClassType classType, int uid) { 148 | binding_oo.oo_set_class_uid(classType.ptr, uid); 149 | } 150 | 151 | /** 152 | * @return the previously set vtable entity for the given class type. 153 | */ 154 | public static Entity getClassVTableEntity(ClassType classType) { 155 | Pointer vtable = binding_oo.oo_get_class_vtable_entity(classType.ptr); 156 | if (vtable == Pointer.NULL) 157 | return null; 158 | return new Entity(vtable); 159 | } 160 | 161 | /** 162 | * lets you specify the entity containing classType's vtable. 163 | * Use an entity with a primitive pointer type, and set the ld name. 164 | */ 165 | public static void setClassVTableEntity(ClassType classType, Entity vtable) { 166 | binding_oo.oo_set_class_vtable_entity(classType.ptr, vtable.ptr); 167 | } 168 | 169 | /** 170 | * lets you specify the entity that represents the pointer to the vtable in an instance 171 | */ 172 | public static void setClassVPtrEntity(ClassType classType, Entity entity) { 173 | binding_oo.oo_set_class_vptr_entity(classType.ptr, entity.ptr); 174 | } 175 | 176 | /** 177 | * returns VPTr entity of a class 178 | */ 179 | public static Entity getClassVPtrEntity(ClassType classType) { 180 | Pointer res = binding_oo.oo_get_class_vptr_entity(classType.ptr); 181 | if (res == null) 182 | return null; 183 | return new Entity(res); 184 | } 185 | 186 | /** 187 | * lets you specify the entity that represents the run-time type info data. 188 | * Use an entity with a primitive pointer type, and set the ld name. 189 | */ 190 | public static void setClassRTTIEntity(ClassType classType, Entity entity) { 191 | binding_oo.oo_set_class_rtti_entity(classType.ptr, entity.ptr); 192 | } 193 | 194 | /** 195 | * lets you specify whether the given classType is representing an interface type 196 | */ 197 | public static void setClassIsInterface(ClassType classType, boolean isInterface) { 198 | binding_oo.oo_set_class_is_interface(classType.ptr, isInterface); 199 | } 200 | 201 | public static boolean getClassIsInterface(ClassType classType) { 202 | return binding_oo.oo_get_class_is_interface(classType.ptr); 203 | } 204 | 205 | public static void setClassIsAbstract(ClassType classType, boolean isAbstract) { 206 | binding_oo.oo_set_class_is_abstract(classType.ptr, isAbstract); 207 | } 208 | 209 | public static boolean getClassIsAbstract(ClassType classType) { 210 | return binding_oo.oo_get_class_is_abstract(classType.ptr); 211 | } 212 | 213 | public static void setClassIsFinal(ClassType classType, boolean isFinal) { 214 | binding_oo.oo_set_class_is_final(classType.ptr, isFinal); 215 | } 216 | 217 | public static boolean getClassIsFinal(ClassType classType) { 218 | return binding_oo.oo_get_class_is_final(classType.ptr); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/firm/RTA.java: -------------------------------------------------------------------------------- 1 | package firm; 2 | 3 | import firm.bindings.binding_rta; 4 | 5 | import com.sun.jna.Pointer; 6 | import java.nio.Buffer; 7 | import java.nio.IntBuffer; 8 | import java.nio.LongBuffer; 9 | 10 | public class RTA { 11 | public static void runRTA(Entity[] entrypoints, Type[] initialLiveClasses) { 12 | binding_rta.rta_optimization(getBufferFromArray(entrypoints, true), getBufferFromArray(initialLiveClasses, true)); 13 | } 14 | 15 | private static Buffer getBufferFromArray(JNAWrapper[] array, boolean nullterminate) { 16 | // taken from jFirm source code src/firm/nodes/Node.java and modified it 17 | // This should be placed in firm.JNAWrapper or similar! 18 | 19 | final int length = array.length; 20 | 21 | // There is no PointerBuffer so ... 22 | if (Pointer.SIZE == 4) { 23 | IntBuffer buffer = (nullterminate) ? IntBuffer.allocate(length+1) : IntBuffer.allocate(length); 24 | for (int i = 0; i < length; ++i) { 25 | buffer.put(i, (int) Pointer.nativeValue(array[i].ptr)); 26 | } 27 | if (nullterminate) 28 | buffer.put(length, 0); 29 | return buffer; 30 | } else if (Pointer.SIZE == 8) { 31 | LongBuffer buffer = (nullterminate) ? LongBuffer.allocate(length+1) : LongBuffer.allocate(length); 32 | for (int i = 0; i < length; ++i) { 33 | buffer.put(i, Pointer.nativeValue(array[i].ptr)); 34 | } 35 | if (nullterminate) 36 | buffer.put(length, 0L); 37 | return buffer; 38 | } else { 39 | /* no 32- or 64-bit architecture */ 40 | throw new RuntimeException("Unsupported architecture"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/firm/bindings/binding_nodes.java: -------------------------------------------------------------------------------- 1 | package firm.bindings; 2 | 3 | /* WARNING: Automatically generated file */ 4 | import com.sun.jna.Native; 5 | import com.sun.jna.Pointer; 6 | 7 | public class binding_nodes { 8 | static { 9 | Native.register("oo"); 10 | } 11 | 12 | public static enum ir_relation { 13 | ir_relation_false(0), 14 | ir_relation_equal((1 << 0)), 15 | ir_relation_less((1 << 1)), 16 | ir_relation_greater((1 << 2)), 17 | ir_relation_unordered((1 << 3)), 18 | ir_relation_less_equal((ir_relation.ir_relation_equal.val | ir_relation.ir_relation_less.val)), 19 | ir_relation_greater_equal((ir_relation.ir_relation_equal.val | ir_relation.ir_relation_greater.val)), 20 | ir_relation_less_greater((ir_relation.ir_relation_less.val | ir_relation.ir_relation_greater.val)), 21 | ir_relation_less_equal_greater(((ir_relation.ir_relation_equal.val | ir_relation.ir_relation_less.val) | ir_relation.ir_relation_greater.val)), 22 | ir_relation_unordered_equal((ir_relation.ir_relation_unordered.val | ir_relation.ir_relation_equal.val)), 23 | ir_relation_unordered_less((ir_relation.ir_relation_unordered.val | ir_relation.ir_relation_less.val)), 24 | ir_relation_unordered_less_equal(((ir_relation.ir_relation_unordered.val | ir_relation.ir_relation_less.val) | ir_relation.ir_relation_equal.val)), 25 | ir_relation_unordered_greater((ir_relation.ir_relation_unordered.val | ir_relation.ir_relation_greater.val)), 26 | ir_relation_unordered_greater_equal(((ir_relation.ir_relation_unordered.val | ir_relation.ir_relation_greater.val) | ir_relation.ir_relation_equal.val)), 27 | ir_relation_unordered_less_greater(((ir_relation.ir_relation_unordered.val | ir_relation.ir_relation_less.val) | ir_relation.ir_relation_greater.val)), 28 | ir_relation_true((((ir_relation.ir_relation_equal.val | ir_relation.ir_relation_less.val) | ir_relation.ir_relation_greater.val) | ir_relation.ir_relation_unordered.val)); 29 | public final int val; 30 | 31 | private static class C { 32 | static int next_val; 33 | } 34 | 35 | ir_relation(int val) { 36 | this.val = val; 37 | C.next_val = val + 1; 38 | } 39 | 40 | ir_relation() { 41 | this.val = C.next_val++; 42 | } 43 | 44 | public static ir_relation getEnum(int val) { 45 | for (ir_relation entry : values()) { 46 | if (val == entry.val) 47 | return entry; 48 | } 49 | return null; 50 | } 51 | } 52 | 53 | public static enum ir_cons_flags { 54 | cons_none(0), 55 | cons_volatile((1 << 0)), 56 | cons_unaligned((1 << 1)), 57 | cons_floats((1 << 2)), 58 | cons_throws_exception((1 << 3)); 59 | public final int val; 60 | 61 | private static class C { 62 | static int next_val; 63 | } 64 | 65 | ir_cons_flags(int val) { 66 | this.val = val; 67 | C.next_val = val + 1; 68 | } 69 | 70 | ir_cons_flags() { 71 | this.val = C.next_val++; 72 | } 73 | 74 | public static ir_cons_flags getEnum(int val) { 75 | for (ir_cons_flags entry : values()) { 76 | if (val == entry.val) 77 | return entry; 78 | } 79 | return null; 80 | } 81 | } 82 | 83 | public static enum op_pin_state { 84 | op_pin_state_floats(0), 85 | op_pin_state_pinned(1), 86 | op_pin_state_exc_pinned(); 87 | public final int val; 88 | 89 | private static class C { 90 | static int next_val; 91 | } 92 | 93 | op_pin_state(int val) { 94 | this.val = val; 95 | C.next_val = val + 1; 96 | } 97 | 98 | op_pin_state() { 99 | this.val = C.next_val++; 100 | } 101 | 102 | public static op_pin_state getEnum(int val) { 103 | for (op_pin_state entry : values()) { 104 | if (val == entry.val) 105 | return entry; 106 | } 107 | return null; 108 | } 109 | } 110 | 111 | public static enum cond_jmp_predicate { 112 | COND_JMP_PRED_NONE(), 113 | COND_JMP_PRED_TRUE(), 114 | COND_JMP_PRED_FALSE(); 115 | public final int val; 116 | 117 | private static class C { 118 | static int next_val; 119 | } 120 | 121 | cond_jmp_predicate(int val) { 122 | this.val = val; 123 | C.next_val = val + 1; 124 | } 125 | 126 | cond_jmp_predicate() { 127 | this.val = C.next_val++; 128 | } 129 | 130 | public static cond_jmp_predicate getEnum(int val) { 131 | for (cond_jmp_predicate entry : values()) { 132 | if (val == entry.val) 133 | return entry; 134 | } 135 | return null; 136 | } 137 | } 138 | 139 | public static enum mtp_additional_properties { 140 | mtp_no_property(0), 141 | mtp_property_no_write((1 << 0)), 142 | mtp_property_pure((1 << 1)), 143 | mtp_property_noreturn((1 << 2)), 144 | mtp_property_terminates((1 << 3)), 145 | mtp_property_nothrow((1 << 4)), 146 | mtp_property_naked((1 << 5)), 147 | mtp_property_malloc((1 << 6)), 148 | mtp_property_returns_twice((1 << 7)), 149 | mtp_property_private((1 << 8)), 150 | mtp_property_always_inline((1 << 9)), 151 | mtp_property_noinline((1 << 10)), 152 | mtp_property_inline_recommended((1 << 11)), 153 | mtp_temporary((1 << 12)); 154 | public final int val; 155 | 156 | private static class C { 157 | static int next_val; 158 | } 159 | 160 | mtp_additional_properties(int val) { 161 | this.val = val; 162 | C.next_val = val + 1; 163 | } 164 | 165 | mtp_additional_properties() { 166 | this.val = C.next_val++; 167 | } 168 | 169 | public static mtp_additional_properties getEnum(int val) { 170 | for (mtp_additional_properties entry : values()) { 171 | if (val == entry.val) 172 | return entry; 173 | } 174 | return null; 175 | } 176 | } 177 | 178 | public static enum ir_builtin_kind { 179 | ir_bk_trap(), 180 | ir_bk_debugbreak(), 181 | ir_bk_return_address(), 182 | ir_bk_frame_address(), 183 | ir_bk_prefetch(), 184 | ir_bk_ffs(), 185 | ir_bk_clz(), 186 | ir_bk_ctz(), 187 | ir_bk_popcount(), 188 | ir_bk_parity(), 189 | ir_bk_bswap(), 190 | ir_bk_inport(), 191 | ir_bk_outport(), 192 | ir_bk_saturating_increment(), 193 | ir_bk_compare_swap(), 194 | ir_bk_may_alias(), 195 | ir_bk_va_start(), 196 | ir_bk_va_arg(), 197 | ir_bk_last(ir_builtin_kind.ir_bk_va_arg.val); 198 | public final int val; 199 | 200 | private static class C { 201 | static int next_val; 202 | } 203 | 204 | ir_builtin_kind(int val) { 205 | this.val = val; 206 | C.next_val = val + 1; 207 | } 208 | 209 | ir_builtin_kind() { 210 | this.val = C.next_val++; 211 | } 212 | 213 | public static ir_builtin_kind getEnum(int val) { 214 | for (ir_builtin_kind entry : values()) { 215 | if (val == entry.val) 216 | return entry; 217 | } 218 | return null; 219 | } 220 | } 221 | 222 | public static enum ir_volatility { 223 | volatility_non_volatile(), 224 | volatility_is_volatile(); 225 | public final int val; 226 | 227 | private static class C { 228 | static int next_val; 229 | } 230 | 231 | ir_volatility(int val) { 232 | this.val = val; 233 | C.next_val = val + 1; 234 | } 235 | 236 | ir_volatility() { 237 | this.val = C.next_val++; 238 | } 239 | 240 | public static ir_volatility getEnum(int val) { 241 | for (ir_volatility entry : values()) { 242 | if (val == entry.val) 243 | return entry; 244 | } 245 | return null; 246 | } 247 | } 248 | 249 | public static enum ir_align { 250 | align_is_aligned(0), 251 | align_non_aligned(); 252 | public final int val; 253 | 254 | private static class C { 255 | static int next_val; 256 | } 257 | 258 | ir_align(int val) { 259 | this.val = val; 260 | C.next_val = val + 1; 261 | } 262 | 263 | ir_align() { 264 | this.val = C.next_val++; 265 | } 266 | 267 | public static ir_align getEnum(int val) { 268 | for (ir_align entry : values()) { 269 | if (val == entry.val) 270 | return entry; 271 | } 272 | return null; 273 | } 274 | } 275 | 276 | public static enum oo_opcode { 277 | ooo_Arraylength(), 278 | ooo_InstanceOf(), 279 | ooo_MethodSel(), 280 | ooo_VptrIsSet(), 281 | ooo_first(oo_opcode.ooo_Arraylength.val), 282 | ooo_last(oo_opcode.ooo_VptrIsSet.val); 283 | public final int val; 284 | 285 | private static class C { 286 | static int next_val; 287 | } 288 | 289 | oo_opcode(int val) { 290 | this.val = val; 291 | C.next_val = val + 1; 292 | } 293 | 294 | oo_opcode() { 295 | this.val = C.next_val++; 296 | } 297 | 298 | public static oo_opcode getEnum(int val) { 299 | for (oo_opcode entry : values()) { 300 | if (val == entry.val) 301 | return entry; 302 | } 303 | return null; 304 | } 305 | } 306 | 307 | public static enum n_Arraylength { 308 | n_Arraylength_mem(), 309 | n_Arraylength_ptr(), 310 | n_Arraylength_max(n_Arraylength.n_Arraylength_ptr.val); 311 | public final int val; 312 | 313 | private static class C { 314 | static int next_val; 315 | } 316 | 317 | n_Arraylength(int val) { 318 | this.val = val; 319 | C.next_val = val + 1; 320 | } 321 | 322 | n_Arraylength() { 323 | this.val = C.next_val++; 324 | } 325 | 326 | public static n_Arraylength getEnum(int val) { 327 | for (n_Arraylength entry : values()) { 328 | if (val == entry.val) 329 | return entry; 330 | } 331 | return null; 332 | } 333 | } 334 | 335 | public static enum pn_Arraylength { 336 | pn_Arraylength_M(), 337 | pn_Arraylength_res(), 338 | pn_Arraylength_max(pn_Arraylength.pn_Arraylength_res.val); 339 | public final int val; 340 | 341 | private static class C { 342 | static int next_val; 343 | } 344 | 345 | pn_Arraylength(int val) { 346 | this.val = val; 347 | C.next_val = val + 1; 348 | } 349 | 350 | pn_Arraylength() { 351 | this.val = C.next_val++; 352 | } 353 | 354 | public static pn_Arraylength getEnum(int val) { 355 | for (pn_Arraylength entry : values()) { 356 | if (val == entry.val) 357 | return entry; 358 | } 359 | return null; 360 | } 361 | } 362 | 363 | public static enum n_InstanceOf { 364 | n_InstanceOf_mem(), 365 | n_InstanceOf_ptr(), 366 | n_InstanceOf_max(n_InstanceOf.n_InstanceOf_ptr.val); 367 | public final int val; 368 | 369 | private static class C { 370 | static int next_val; 371 | } 372 | 373 | n_InstanceOf(int val) { 374 | this.val = val; 375 | C.next_val = val + 1; 376 | } 377 | 378 | n_InstanceOf() { 379 | this.val = C.next_val++; 380 | } 381 | 382 | public static n_InstanceOf getEnum(int val) { 383 | for (n_InstanceOf entry : values()) { 384 | if (val == entry.val) 385 | return entry; 386 | } 387 | return null; 388 | } 389 | } 390 | 391 | public static enum pn_InstanceOf { 392 | pn_InstanceOf_M(), 393 | pn_InstanceOf_res(), 394 | pn_InstanceOf_max(pn_InstanceOf.pn_InstanceOf_res.val); 395 | public final int val; 396 | 397 | private static class C { 398 | static int next_val; 399 | } 400 | 401 | pn_InstanceOf(int val) { 402 | this.val = val; 403 | C.next_val = val + 1; 404 | } 405 | 406 | pn_InstanceOf() { 407 | this.val = C.next_val++; 408 | } 409 | 410 | public static pn_InstanceOf getEnum(int val) { 411 | for (pn_InstanceOf entry : values()) { 412 | if (val == entry.val) 413 | return entry; 414 | } 415 | return null; 416 | } 417 | } 418 | 419 | public static enum n_MethodSel { 420 | n_MethodSel_mem(), 421 | n_MethodSel_ptr(), 422 | n_MethodSel_max(n_MethodSel.n_MethodSel_ptr.val); 423 | public final int val; 424 | 425 | private static class C { 426 | static int next_val; 427 | } 428 | 429 | n_MethodSel(int val) { 430 | this.val = val; 431 | C.next_val = val + 1; 432 | } 433 | 434 | n_MethodSel() { 435 | this.val = C.next_val++; 436 | } 437 | 438 | public static n_MethodSel getEnum(int val) { 439 | for (n_MethodSel entry : values()) { 440 | if (val == entry.val) 441 | return entry; 442 | } 443 | return null; 444 | } 445 | } 446 | 447 | public static enum pn_MethodSel { 448 | pn_MethodSel_M(), 449 | pn_MethodSel_res(), 450 | pn_MethodSel_max(pn_MethodSel.pn_MethodSel_res.val); 451 | public final int val; 452 | 453 | private static class C { 454 | static int next_val; 455 | } 456 | 457 | pn_MethodSel(int val) { 458 | this.val = val; 459 | C.next_val = val + 1; 460 | } 461 | 462 | pn_MethodSel() { 463 | this.val = C.next_val++; 464 | } 465 | 466 | public static pn_MethodSel getEnum(int val) { 467 | for (pn_MethodSel entry : values()) { 468 | if (val == entry.val) 469 | return entry; 470 | } 471 | return null; 472 | } 473 | } 474 | 475 | public static enum n_VptrIsSet { 476 | n_VptrIsSet_mem(), 477 | n_VptrIsSet_ptr(), 478 | n_VptrIsSet_max(n_VptrIsSet.n_VptrIsSet_ptr.val); 479 | public final int val; 480 | 481 | private static class C { 482 | static int next_val; 483 | } 484 | 485 | n_VptrIsSet(int val) { 486 | this.val = val; 487 | C.next_val = val + 1; 488 | } 489 | 490 | n_VptrIsSet() { 491 | this.val = C.next_val++; 492 | } 493 | 494 | public static n_VptrIsSet getEnum(int val) { 495 | for (n_VptrIsSet entry : values()) { 496 | if (val == entry.val) 497 | return entry; 498 | } 499 | return null; 500 | } 501 | } 502 | 503 | public static enum pn_VptrIsSet { 504 | pn_VptrIsSet_M(), 505 | pn_VptrIsSet_res(), 506 | pn_VptrIsSet_max(pn_VptrIsSet.pn_VptrIsSet_res.val); 507 | public final int val; 508 | 509 | private static class C { 510 | static int next_val; 511 | } 512 | 513 | pn_VptrIsSet(int val) { 514 | this.val = val; 515 | C.next_val = val + 1; 516 | } 517 | 518 | pn_VptrIsSet() { 519 | this.val = C.next_val++; 520 | } 521 | 522 | public static pn_VptrIsSet getEnum(int val) { 523 | for (pn_VptrIsSet entry : values()) { 524 | if (val == entry.val) 525 | return entry; 526 | } 527 | return null; 528 | } 529 | } 530 | 531 | 532 | public static native int is_oo_node(Pointer node); 533 | 534 | public static native /* oo_opcode */int get_oo_irn_opcode(Pointer node); 535 | 536 | public static native Pointer new_rd_Arraylength(Pointer dbgi, Pointer block, Pointer irn_mem, Pointer irn_ptr); 537 | 538 | public static native Pointer new_r_Arraylength(Pointer block, Pointer irn_mem, Pointer irn_ptr); 539 | 540 | public static native Pointer new_d_Arraylength(Pointer dbgi, Pointer irn_mem, Pointer irn_ptr); 541 | 542 | public static native Pointer new_Arraylength(Pointer irn_mem, Pointer irn_ptr); 543 | 544 | public static native int is_Arraylength(Pointer node); 545 | 546 | public static native Pointer get_Arraylength_mem(Pointer node); 547 | 548 | public static native void set_Arraylength_mem(Pointer node, Pointer mem); 549 | 550 | public static native Pointer get_Arraylength_ptr(Pointer node); 551 | 552 | public static native void set_Arraylength_ptr(Pointer node, Pointer ptr); 553 | 554 | public static native Pointer get_op_Arraylength(); 555 | 556 | public static native Pointer new_rd_InstanceOf(Pointer dbgi, Pointer block, Pointer irn_mem, Pointer irn_ptr, Pointer type); 557 | 558 | public static native Pointer new_r_InstanceOf(Pointer block, Pointer irn_mem, Pointer irn_ptr, Pointer type); 559 | 560 | public static native Pointer new_d_InstanceOf(Pointer dbgi, Pointer irn_mem, Pointer irn_ptr, Pointer type); 561 | 562 | public static native Pointer new_InstanceOf(Pointer irn_mem, Pointer irn_ptr, Pointer type); 563 | 564 | public static native int is_InstanceOf(Pointer node); 565 | 566 | public static native Pointer get_InstanceOf_mem(Pointer node); 567 | 568 | public static native void set_InstanceOf_mem(Pointer node, Pointer mem); 569 | 570 | public static native Pointer get_InstanceOf_ptr(Pointer node); 571 | 572 | public static native void set_InstanceOf_ptr(Pointer node, Pointer ptr); 573 | 574 | public static native Pointer get_InstanceOf_type(Pointer node); 575 | 576 | public static native void set_InstanceOf_type(Pointer node, Pointer type); 577 | 578 | public static native Pointer get_op_InstanceOf(); 579 | 580 | public static native Pointer new_rd_MethodSel(Pointer dbgi, Pointer block, Pointer irn_mem, Pointer irn_ptr, Pointer entity); 581 | 582 | public static native Pointer new_r_MethodSel(Pointer block, Pointer irn_mem, Pointer irn_ptr, Pointer entity); 583 | 584 | public static native Pointer new_d_MethodSel(Pointer dbgi, Pointer irn_mem, Pointer irn_ptr, Pointer entity); 585 | 586 | public static native Pointer new_MethodSel(Pointer irn_mem, Pointer irn_ptr, Pointer entity); 587 | 588 | public static native int is_MethodSel(Pointer node); 589 | 590 | public static native Pointer get_MethodSel_mem(Pointer node); 591 | 592 | public static native void set_MethodSel_mem(Pointer node, Pointer mem); 593 | 594 | public static native Pointer get_MethodSel_ptr(Pointer node); 595 | 596 | public static native void set_MethodSel_ptr(Pointer node, Pointer ptr); 597 | 598 | public static native Pointer get_MethodSel_entity(Pointer node); 599 | 600 | public static native void set_MethodSel_entity(Pointer node, Pointer entity); 601 | 602 | public static native Pointer get_op_MethodSel(); 603 | 604 | public static native Pointer new_rd_VptrIsSet(Pointer dbgi, Pointer block, Pointer irn_mem, Pointer irn_ptr, Pointer type); 605 | 606 | public static native Pointer new_r_VptrIsSet(Pointer block, Pointer irn_mem, Pointer irn_ptr, Pointer type); 607 | 608 | public static native Pointer new_d_VptrIsSet(Pointer dbgi, Pointer irn_mem, Pointer irn_ptr, Pointer type); 609 | 610 | public static native Pointer new_VptrIsSet(Pointer irn_mem, Pointer irn_ptr, Pointer type); 611 | 612 | public static native int is_VptrIsSet(Pointer node); 613 | 614 | public static native Pointer get_VptrIsSet_mem(Pointer node); 615 | 616 | public static native void set_VptrIsSet_mem(Pointer node, Pointer mem); 617 | 618 | public static native Pointer get_VptrIsSet_ptr(Pointer node); 619 | 620 | public static native void set_VptrIsSet_ptr(Pointer node, Pointer ptr); 621 | 622 | public static native Pointer get_VptrIsSet_type(Pointer node); 623 | 624 | public static native void set_VptrIsSet_type(Pointer node, Pointer type); 625 | 626 | public static native Pointer get_op_VptrIsSet(); 627 | } 628 | -------------------------------------------------------------------------------- /src/firm/oo/nodes/Arraylength.java: -------------------------------------------------------------------------------- 1 | /* Warning: Automatically generated file */ 2 | package firm.oo.nodes; 3 | 4 | import com.sun.jna.Pointer; 5 | import firm.bindings.binding_ircons; 6 | import firm.nodes.Node; 7 | import firm.nodes.NodeVisitor; 8 | import firm.nodes.NodeWrapperFactory; 9 | import firm.Construction; 10 | 11 | public class Arraylength extends Node { 12 | static class Factory implements NodeWrapperFactory { 13 | @Override 14 | public Node createWrapper(Pointer ptr) { 15 | return new Arraylength(ptr); 16 | } 17 | } 18 | 19 | static void init() { 20 | Pointer op = firm.bindings.binding_nodes.get_op_Arraylength(); 21 | Node.registerFactory(firm.bindings.binding_irop.get_op_code(op), new Factory()); 22 | } 23 | public static Node create(Node block, Node mem, Node _ptr) { 24 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_Arraylength(block.ptr, mem.ptr, _ptr.ptr)); 25 | } 26 | 27 | public static Node create(Construction cons, Node mem, Node _ptr) { 28 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_Arraylength(binding_ircons.get_r_cur_block(cons.getGraph().ptr), mem.ptr, _ptr.ptr)); 29 | } 30 | 31 | public Arraylength(Pointer ptr) { 32 | super(ptr); 33 | } 34 | 35 | public Node getMem() { 36 | return createWrapper(firm.bindings.binding_nodes.get_Arraylength_mem(ptr)); 37 | } 38 | 39 | public void setMem(Node mem) { 40 | firm.bindings.binding_nodes.set_Arraylength_mem(this.ptr, mem.ptr); 41 | } 42 | 43 | public Node getPtr() { 44 | return createWrapper(firm.bindings.binding_nodes.get_Arraylength_ptr(ptr)); 45 | } 46 | 47 | public void setPtr(Node _ptr) { 48 | firm.bindings.binding_nodes.set_Arraylength_ptr(this.ptr, _ptr.ptr); 49 | } 50 | 51 | @Override 52 | public void accept(NodeVisitor visitor) { 53 | visitor.visitUnknown(this); 54 | } 55 | 56 | /** memory result */ 57 | public static final int pnM = 0; 58 | 59 | /** length of the array */ 60 | public static final int pnRes = 1; 61 | 62 | public static final int pnMax = 2; 63 | } 64 | -------------------------------------------------------------------------------- /src/firm/oo/nodes/InstanceOf.java: -------------------------------------------------------------------------------- 1 | /* Warning: Automatically generated file */ 2 | package firm.oo.nodes; 3 | 4 | import com.sun.jna.Pointer; 5 | import firm.bindings.binding_ircons; 6 | import firm.nodes.Node; 7 | import firm.nodes.NodeVisitor; 8 | import firm.nodes.NodeWrapperFactory; 9 | import firm.Construction; 10 | 11 | public class InstanceOf extends Node { 12 | static class Factory implements NodeWrapperFactory { 13 | @Override 14 | public Node createWrapper(Pointer ptr) { 15 | return new InstanceOf(ptr); 16 | } 17 | } 18 | 19 | static void init() { 20 | Pointer op = firm.bindings.binding_nodes.get_op_InstanceOf(); 21 | Node.registerFactory(firm.bindings.binding_irop.get_op_code(op), new Factory()); 22 | } 23 | public static Node create(Node block, Node mem, Node _ptr, firm.Type type) { 24 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_InstanceOf(block.ptr, mem.ptr, _ptr.ptr, type.ptr)); 25 | } 26 | 27 | public static Node create(Construction cons, Node mem, Node _ptr, firm.Type type) { 28 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_InstanceOf(binding_ircons.get_r_cur_block(cons.getGraph().ptr), mem.ptr, _ptr.ptr, type.ptr)); 29 | } 30 | 31 | public InstanceOf(Pointer ptr) { 32 | super(ptr); 33 | } 34 | 35 | public Node getMem() { 36 | return createWrapper(firm.bindings.binding_nodes.get_InstanceOf_mem(ptr)); 37 | } 38 | 39 | public void setMem(Node mem) { 40 | firm.bindings.binding_nodes.set_InstanceOf_mem(this.ptr, mem.ptr); 41 | } 42 | 43 | public Node getPtr() { 44 | return createWrapper(firm.bindings.binding_nodes.get_InstanceOf_ptr(ptr)); 45 | } 46 | 47 | public void setPtr(Node _ptr) { 48 | firm.bindings.binding_nodes.set_InstanceOf_ptr(this.ptr, _ptr.ptr); 49 | } 50 | 51 | public firm.Type getType() { 52 | Pointer _res = firm.bindings.binding_nodes.get_InstanceOf_type(ptr); 53 | return firm.Type.createWrapper(_res); 54 | } 55 | 56 | public void setType(firm.Type _val) { 57 | firm.bindings.binding_nodes.set_InstanceOf_type(this.ptr, _val.ptr); 58 | } 59 | 60 | @Override 61 | public void accept(NodeVisitor visitor) { 62 | visitor.visitUnknown(this); 63 | } 64 | 65 | /** memory result */ 66 | public static final int pnM = 0; 67 | 68 | /** result of instanceof check */ 69 | public static final int pnRes = 1; 70 | 71 | public static final int pnMax = 2; 72 | } 73 | -------------------------------------------------------------------------------- /src/firm/oo/nodes/MethodSel.java: -------------------------------------------------------------------------------- 1 | /* Warning: Automatically generated file */ 2 | package firm.oo.nodes; 3 | 4 | import com.sun.jna.Pointer; 5 | import firm.bindings.binding_ircons; 6 | import firm.nodes.Node; 7 | import firm.nodes.NodeVisitor; 8 | import firm.nodes.NodeWrapperFactory; 9 | import firm.Construction; 10 | 11 | public class MethodSel extends Node { 12 | static class Factory implements NodeWrapperFactory { 13 | @Override 14 | public Node createWrapper(Pointer ptr) { 15 | return new MethodSel(ptr); 16 | } 17 | } 18 | 19 | static void init() { 20 | Pointer op = firm.bindings.binding_nodes.get_op_MethodSel(); 21 | Node.registerFactory(firm.bindings.binding_irop.get_op_code(op), new Factory()); 22 | } 23 | public static Node create(Node block, Node mem, Node _ptr, firm.Entity entity) { 24 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_MethodSel(block.ptr, mem.ptr, _ptr.ptr, entity.ptr)); 25 | } 26 | 27 | public static Node create(Construction cons, Node mem, Node _ptr, firm.Entity entity) { 28 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_MethodSel(binding_ircons.get_r_cur_block(cons.getGraph().ptr), mem.ptr, _ptr.ptr, entity.ptr)); 29 | } 30 | 31 | public MethodSel(Pointer ptr) { 32 | super(ptr); 33 | } 34 | 35 | public Node getMem() { 36 | return createWrapper(firm.bindings.binding_nodes.get_MethodSel_mem(ptr)); 37 | } 38 | 39 | public void setMem(Node mem) { 40 | firm.bindings.binding_nodes.set_MethodSel_mem(this.ptr, mem.ptr); 41 | } 42 | 43 | public Node getPtr() { 44 | return createWrapper(firm.bindings.binding_nodes.get_MethodSel_ptr(ptr)); 45 | } 46 | 47 | public void setPtr(Node _ptr) { 48 | firm.bindings.binding_nodes.set_MethodSel_ptr(this.ptr, _ptr.ptr); 49 | } 50 | 51 | public firm.Entity getEntity() { 52 | Pointer _res = firm.bindings.binding_nodes.get_MethodSel_entity(ptr); 53 | return new firm.Entity(_res); 54 | } 55 | 56 | public void setEntity(firm.Entity _val) { 57 | firm.bindings.binding_nodes.set_MethodSel_entity(this.ptr, _val.ptr); 58 | } 59 | 60 | @Override 61 | public void accept(NodeVisitor visitor) { 62 | visitor.visitUnknown(this); 63 | } 64 | 65 | /** memory result */ 66 | public static final int pnM = 0; 67 | 68 | /** address of method */ 69 | public static final int pnRes = 1; 70 | 71 | public static final int pnMax = 2; 72 | } 73 | -------------------------------------------------------------------------------- /src/firm/oo/nodes/Nodes.java: -------------------------------------------------------------------------------- 1 | /* Warning: Automatically generated file */ 2 | package firm.oo.nodes; 3 | 4 | public class Nodes { 5 | public static void init() { 6 | Arraylength.init(); 7 | InstanceOf.init(); 8 | MethodSel.init(); 9 | VptrIsSet.init(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/firm/oo/nodes/VptrIsSet.java: -------------------------------------------------------------------------------- 1 | /* Warning: Automatically generated file */ 2 | package firm.oo.nodes; 3 | 4 | import com.sun.jna.Pointer; 5 | import firm.bindings.binding_ircons; 6 | import firm.nodes.Node; 7 | import firm.nodes.NodeVisitor; 8 | import firm.nodes.NodeWrapperFactory; 9 | import firm.Construction; 10 | 11 | public class VptrIsSet extends Node { 12 | static class Factory implements NodeWrapperFactory { 13 | @Override 14 | public Node createWrapper(Pointer ptr) { 15 | return new VptrIsSet(ptr); 16 | } 17 | } 18 | 19 | static void init() { 20 | Pointer op = firm.bindings.binding_nodes.get_op_VptrIsSet(); 21 | Node.registerFactory(firm.bindings.binding_irop.get_op_code(op), new Factory()); 22 | } 23 | public static Node create(Node block, Node mem, Node _ptr, firm.Type type) { 24 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_VptrIsSet(block.ptr, mem.ptr, _ptr.ptr, type.ptr)); 25 | } 26 | 27 | public static Node create(Construction cons, Node mem, Node _ptr, firm.Type type) { 28 | return Node.createWrapper(firm.bindings.binding_nodes.new_r_VptrIsSet(binding_ircons.get_r_cur_block(cons.getGraph().ptr), mem.ptr, _ptr.ptr, type.ptr)); 29 | } 30 | 31 | public VptrIsSet(Pointer ptr) { 32 | super(ptr); 33 | } 34 | 35 | public Node getMem() { 36 | return createWrapper(firm.bindings.binding_nodes.get_VptrIsSet_mem(ptr)); 37 | } 38 | 39 | public void setMem(Node mem) { 40 | firm.bindings.binding_nodes.set_VptrIsSet_mem(this.ptr, mem.ptr); 41 | } 42 | 43 | public Node getPtr() { 44 | return createWrapper(firm.bindings.binding_nodes.get_VptrIsSet_ptr(ptr)); 45 | } 46 | 47 | public void setPtr(Node _ptr) { 48 | firm.bindings.binding_nodes.set_VptrIsSet_ptr(this.ptr, _ptr.ptr); 49 | } 50 | 51 | public firm.Type getType() { 52 | Pointer _res = firm.bindings.binding_nodes.get_VptrIsSet_type(ptr); 53 | return firm.Type.createWrapper(_res); 54 | } 55 | 56 | public void setType(firm.Type _val) { 57 | firm.bindings.binding_nodes.set_VptrIsSet_type(this.ptr, _val.ptr); 58 | } 59 | 60 | @Override 61 | public void accept(NodeVisitor visitor) { 62 | visitor.visitUnknown(this); 63 | } 64 | 65 | /** memory result */ 66 | public static final int pnM = 0; 67 | 68 | /** pointer to object */ 69 | public static final int pnRes = 1; 70 | 71 | public static final int pnMax = 2; 72 | } 73 | --------------------------------------------------------------------------------