Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
This combines the .o emission code from JuliaLang#5787 with some error checking code
for cpuid mismatch. When releasing a binary, set JULIA_CPU_TARGET to "core2"
(we discussed that this is a reasonable minimum) in your Make.user and
everything should work just fine.
  • Loading branch information
Keno committed Mar 19, 2014
1 parent 9a5c276 commit c90c0af
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 25 deletions.
27 changes: 20 additions & 7 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ USE_INTEL_JITEVENTS = 0
# libc++ is standard on OS X 10.9, but not for earlier releases
USE_LIBCPP = 0

# Select the cpu architecture to target
# Current available options are "native" and "core2"
JULIA_CPU_TARGET = native

# we include twice to pickup user definitions better
ifeq (exists, $(shell [ -e $(JULIAHOME)/Make.user ] && echo exists ))
include $(JULIAHOME)/Make.user
Expand Down Expand Up @@ -207,7 +211,8 @@ $(error Address Sanitizer only supported with clang. Try setting SANITIZE=0)
endif
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
JCFLAGS = -std=gnu99 -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64
JCFLAGS = -std=gnu99 -pipe $(fPIC) -fno-strict-aliasing
JCPPFLAGS = -D_FILE_OFFSET_BITS=64
JCXXFLAGS = -pipe $(fPIC) -fno-rtti
DEBUGFLAGS = -O0 -ggdb3 -DDEBUG -fstack-protector-all
SHIPFLAGS = -O3 -falign-functions
Expand All @@ -216,7 +221,8 @@ endif
ifeq ($(USECLANG),1)
CC = $(CROSS_COMPILE)clang
CXX = $(CROSS_COMPILE)clang++
JCFLAGS = -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64
JCFLAGS = -pipe $(fPIC) -fno-strict-aliasing
JCPPFLAGS = -D_FILE_OFFSET_BITS=64
JCXXFLAGS = -pipe $(fPIC) -fno-rtti
DEBUGFLAGS = -O0 -g -DDEBUG -fstack-protector-all
SHIPFLAGS = -O3
Expand All @@ -229,7 +235,7 @@ else
CC += $(STDLIBCPP_FLAG) -mmacosx-version-min=10.6
CXX += $(STDLIBCPP_FLAG) -mmacosx-version-min=10.6
endif
JCFLAGS += -D_LARGEFILE_SOURCE -D_DARWIN_USE_64_BIT_INODE=1
JCPPFLAGS += -D_LARGEFILE_SOURCE -D_DARWIN_USE_64_BIT_INODE=1
endif
endif

Expand All @@ -241,6 +247,14 @@ AS := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
RANLIB := $(CROSS_COMPILE)ranlib

ifeq ($(JULIA_CPU_TARGET),native)
JCPPFLAGS += -DJULIA_TARGET_NATIVE
else ifeq ($(JULIA_CPU_TARGET),core2)
JCPPFLAGS += -DJULIA_TARGET_CORE2
else
$(error Unknown cpu target architecture)
endif


# Calculate relative paths to libdir and private_libdir
build_libdir_rel = $(shell $(JULIAHOME)/contrib/relative_path.sh $(build_bindir) $(build_libdir))
Expand All @@ -250,7 +264,7 @@ build_private_libdir_rel = $(shell $(JULIAHOME)/contrib/relative_path.sh $(build
private_libdir_rel = $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(private_libdir))

# if not absolute, then relative to the directory of the julia executable
JCFLAGS += "-DJL_SYSTEM_IMAGE_PATH=\"$(build_private_libdir_rel)/sys.ji\""
JCPPFLAGS += "-DJL_SYSTEM_IMAGE_PATH=\"$(build_private_libdir_rel)/sys.ji\""

# On Windows, we want shared library files to end up in $(build_bindir), instead of $(build_libdir)
ifeq ($(OS),WINNT)
Expand Down Expand Up @@ -321,7 +335,7 @@ endif
else
ifeq ($(OS),Darwin)
LIBUNWIND=$(build_libdir)/libosxunwind.a
JCFLAGS+=-DLIBOSXUNWIND
JCPPFLAGS+=-DLIBOSXUNWIND
else
LIBUNWIND=$(build_libdir)/libunwind-generic.a $(build_libdir)/libunwind.a
endif
Expand Down Expand Up @@ -485,8 +499,7 @@ endif
ifeq ($(OS), WINNT)
OSLIBS += -Wl,--export-all-symbols -Wl,--version-script=$(JULIAHOME)/src/julia.expmap \
$(NO_WHOLE_ARCHIVE) -lpsapi -lkernel32 -lws2_32 -liphlpapi -lwinmm -ldbghelp -lssp
JCFLAGS += -D_WIN32_WINNT=0x0600
JCXXFLAGS += -D_WIN32_WINNT=0x0600
JCPPFLAGS += -D_WIN32_WINNT=0x0600
JLDFLAGS = -Wl,--stack,8388608
ifeq ($(ARCH),i686)
JLDFLAGS += -Wl,--large-address-aware
Expand Down
9 changes: 3 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ $(build_sysconfdir)/julia/juliarc.jl: contrib/windows/juliarc.jl
endif

# use sys.ji if it exists, otherwise run two stages
$(build_private_libdir)/sys%ji: $(build_private_libdir)/sys%bc

$(build_private_libdir)/sys%o: $(build_private_libdir)/sys%bc
$(call spawn,$(LLVM_LLC)) -filetype=obj -relocation-model=pic -mattr=-bmi2,-avx2 -o $(call cygpath_w,$@) $(call cygpath_w,$<)
$(build_private_libdir)/sys%ji: $(build_private_libdir)/sys%o

.PRECIOUS: $(build_private_libdir)/sys%o

Expand All @@ -77,11 +74,11 @@ $(build_private_libdir)/sys%$(SHLIB_EXT): $(build_private_libdir)/sys%o
$$([ $(OS) = Darwin ] && echo -Wl,-undefined,dynamic_lookup || echo -Wl,--unresolved-symbols,ignore-all ) \
$$([ $(OS) = WINNT ] && echo -ljulia -lssp)

$(build_private_libdir)/sys0.bc:
$(build_private_libdir)/sys0.o:
@$(QUIET_JULIA) cd base && \
$(call spawn,$(JULIA_EXECUTABLE)) --build $(call cygpath_w,$(build_private_libdir)/sys0) sysimg.jl

$(build_private_libdir)/sys.bc: VERSION base/*.jl base/pkg/*.jl base/linalg/*.jl base/sparse/*.jl $(build_datarootdir)/julia/helpdb.jl $(build_datarootdir)/man/man1/julia.1 $(build_private_libdir)/sys0.$(SHLIB_EXT)
$(build_private_libdir)/sys.o: VERSION base/*.jl base/pkg/*.jl base/linalg/*.jl base/sparse/*.jl $(build_datarootdir)/julia/helpdb.jl $(build_datarootdir)/man/man1/julia.1 $(build_private_libdir)/sys0.$(SHLIB_EXT)
@$(QUIET_JULIA) cd base && \
$(call spawn,$(JULIA_EXECUTABLE)) --build $(call cygpath_w,$(build_private_libdir)/sys) \
-J$(call cygpath_w,$(build_private_libdir))/$$([ -e $(build_private_libdir)/sys.ji ] && echo sys.ji || echo sys0.ji) -f sysimg.jl \
Expand Down
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ include $(JULIAHOME)/deps/Versions.make

override CFLAGS += $(JCFLAGS)
override CXXFLAGS += $(JCXXFLAGS)
override CPPFLAGS += $(JCPPFLAGS)

SRCS = \
jltypes gf ast builtins module codegen interpreter \
Expand Down
28 changes: 28 additions & 0 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ extern "C" int32_t jl_get_llvm_gv(jl_value_t *p)
return 0;
return it->second.index;
}

extern "C" {
extern void cpuid(int32_t CPUInfo[4], int32_t InfoType);
}

static void jl_gen_llvm_gv_array()
{
// emit the variable table into the code image (can only call this once)
Expand All @@ -234,6 +239,29 @@ static void jl_gen_llvm_gv_array()
GlobalVariable::ExternalLinkage,
ConstantInt::get(T_size,globalUnique+1),
"jl_globalUnique");

Constant *feature_string = ConstantDataArray::getString(jl_LLVMContext,jl_cpu_string);
new GlobalVariable(
*jl_Module,
feature_string->getType(),
true,
GlobalVariable::ExternalLinkage,
feature_string,
"jl_sysimg_cpu_target");

// For native also store the cpuid
if(strcmp(jl_cpu_string,"native") == 0) {
uint32_t info[4];

cpuid((int32_t*)info, 1);
new GlobalVariable(
*jl_Module,
T_int64,
true,
GlobalVariable::ExternalLinkage,
ConstantInt::get(T_int64,((uint64_t)info[2])|(((uint64_t)info[3])<<32)),
"jl_sysimg_cpu_cpuid");
}
}

static int32_t jl_assign_functionID(Function *functionObject)
Expand Down
72 changes: 66 additions & 6 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/PassManager.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Bitcode/ReaderWriter.h"
#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5
#define LLVM35 1
#include "llvm/IR/Verifier.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/AsmParser/Parser.h"
#else
Expand Down Expand Up @@ -80,6 +83,7 @@
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Instrumentation.h"
#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 1
#include "llvm/Transforms/Vectorize.h"
#endif
Expand Down Expand Up @@ -127,6 +131,7 @@ static LLVMContext &jl_LLVMContext = getGlobalContext();
static IRBuilder<> builder(getGlobalContext());
static bool nested_compile=false;
static ExecutionEngine *jl_ExecutionEngine;
static TargetMachine *jl_TargetMachine;
#ifdef USE_MCJIT
static Module *shadow_module;
static RTDyldMemoryManager *jl_mcjmm;
Expand Down Expand Up @@ -302,6 +307,47 @@ void jl_dump_bitcode(char* fname)
#endif
}

extern "C"
void jl_dump_objfile(char* fname, int jit_model)
{
std::string err;
raw_fd_ostream OS(fname, err);
formatted_raw_ostream FOS(OS);
jl_gen_llvm_gv_array();

// We don't want to use MCJIT's target machine because
// it uses the large code model and we may potentially
// want less optimizations there.
OwningPtr<TargetMachine>
TM(jl_TargetMachine->getTarget().createTargetMachine(
jl_TargetMachine->getTargetTriple(),
jl_TargetMachine->getTargetCPU(),
jl_TargetMachine->getTargetFeatureString(),
jl_TargetMachine->Options,
#ifdef _OS_LINUX_
Reloc::PIC_,
#else
jit_model ? Reloc::PIC_ : Reloc::Default,
#endif
jit_model ? CodeModel::JITDefault : CodeModel::Default,
CodeGenOpt::Aggressive // -O3
));

PassManager PM;
PM.add(new TargetLibraryInfo(Triple(jl_TargetMachine->getTargetTriple())));
PM.add(new DataLayout(*jl_ExecutionEngine->getDataLayout()));
if (TM->addPassesToEmitFile(PM, FOS,
TargetMachine::CGFT_ObjectFile, false)) {
jl_error("Could not generate obj file for this target");
}

#ifdef USE_MCJIT
PM.run(*shadow_module);
#else
PM.run(*jl_Module);
#endif
}

// aggregate of array metadata
typedef struct {
Value *dataptr;
Expand Down Expand Up @@ -366,13 +412,20 @@ static Type *NoopType;

// --- utilities ---

#if defined(JULIA_TARGET_CORE2)
const char *jl_cpu_string = "core2";
#elif defined(JULIA_TARGET_NATIVE)
const char *jl_cpu_string = "native";
#else
#error "Must select julia cpu target"
#endif

extern "C" {
int globalUnique = 0;
}

#include "cgutils.cpp"


static void jl_rethrow_with_add(const char *fmt, ...)
{
if (jl_typeis(jl_exception_in_transit, jl_errorexception_type)) {
Expand Down Expand Up @@ -4082,23 +4135,30 @@ extern "C" void jl_init_codegen(void)
#endif
#ifdef USE_MCJIT
jl_mcjmm = new SectionMemoryManager();
#endif
#else
// Temporarily disable Haswell BMI2 features due to LLVM bug.
const char *mattr[] = {"-bmi2", "-avx2"};
#endif
std::vector<std::string> attrvec (mattr, mattr+2);
jl_ExecutionEngine = EngineBuilder(engine_module)
EngineBuilder eb = EngineBuilder(engine_module)
.setEngineKind(EngineKind::JIT)
#if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_)
.setJITMemoryManager(new JITMemoryManagerWin())
#endif
.setTargetOptions(options)
#if defined(JULIA_TARGET_NATIVE)
.setMCPU("")
#else
.setMCPU(jl_cpu_string)
#endif
#ifdef USE_MCJIT
.setUseMCJIT(true)
.setMAttrs(attrvec)
.setMAttrs(attrvec);
#else
.setMAttrs(attrvec)
.setMAttrs(attrvec);
#endif
.create();
jl_TargetMachine = eb.selectTarget();
jl_ExecutionEngine = eb.create(jl_TargetMachine);
#endif // LLVM VERSION
jl_ExecutionEngine->DisableLazyCompilation();

Expand Down
22 changes: 21 additions & 1 deletion src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,11 @@ static void write_as_tag(ios_t *s, uint8_t tag)
static void jl_serialize_value_(ios_t *s, jl_value_t *v);
static jl_value_t *jl_deserialize_value(ios_t *s);
static jl_value_t *jl_deserialize_value_internal(ios_t *s);
static jl_value_t ***sysimg_gvars = NULL;
jl_value_t ***sysimg_gvars = NULL;

extern int globalUnique;
extern void cpuid(int32_t CPUInfo[4], int32_t InfoType);
extern const char *jl_cpu_string;

static void jl_load_sysimg_so(char *fname)
{
Expand All @@ -108,6 +110,24 @@ static void jl_load_sysimg_so(char *fname)
if (sysimg_handle != 0) {
sysimg_gvars = (jl_value_t***)jl_dlsym(sysimg_handle, "jl_sysimg_gvars");
globalUnique = *(size_t*)jl_dlsym(sysimg_handle, "jl_globalUnique");
const char *cpu_target = (const char*)jl_dlsym(sysimg_handle, "jl_sysimg_cpu_target");
if (strcmp(cpu_target,jl_cpu_string) != 0)
jl_error("Julia and the system image were compiled for different architectures.");
uint32_t info[4];
cpuid((int32_t*)info, 1);
if (strcmp(cpu_target,"native") == 0)
{
uint64_t saved_cpuid = *(uint64_t*)jl_dlsym(sysimg_handle, "jl_sysimg_cpu_cpuid");
if (saved_cpuid != (((uint64_t)info[2])|(((uint64_t)info[3])<<32)))
jl_error("Target architecture mismatch. Please regenerate sys.{so,dll,dylib}.");
} else if(strcmp(cpu_target,"core2") == 0) {
int HasSSSE3 = (info[3] & 1<<9);
if (!HasSSSE3)
jl_error("The current host does not support SSSE3, but the system image was compiled for Core2.\n"
"Please delete or regenerate sys.{so,dll,dylib}.");
} else {
jl_error("System image has unknown target cpu architecture.");
}
}
else {
sysimg_gvars = 0;
Expand Down
10 changes: 5 additions & 5 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,13 +867,13 @@ DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *
if (asprintf(&build_ji, "%s.ji",build_path) > 0) {
jl_save_system_image(build_ji);
free(build_ji);
char *build_bc;
if (asprintf(&build_bc, "%s.bc",build_path) > 0) {
jl_dump_bitcode(build_bc);
free(build_bc);
char *build_o;
if (asprintf(&build_o, "%s.o",build_path) > 0) {
jl_dump_objfile(build_o,0);
free(build_o);
}
else {
ios_printf(ios_stderr,"FATAL: failed to create string for .bc build path");
ios_printf(ios_stderr,"FATAL: failed to create string for .o build path");
}
}
else {
Expand Down
1 change: 1 addition & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void jl_init_tasks(void *stack, size_t ssize);
void jl_init_serializer(void);

void jl_dump_bitcode(char *fname);
void jl_dump_objfile(char *fname, int jit_model);
int32_t jl_get_llvm_gv(jl_value_t *p);

#ifdef _OS_LINUX_
Expand Down
1 change: 1 addition & 0 deletions ui/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include $(JULIAHOME)/Make.inc

override CFLAGS += $(JCFLAGS)
override CXXFLAGS += $(JCXXFLAGS)
override CPPFLAGS += $(JCPPFLAGS)

FLAGS = -Wall -Wno-strict-aliasing -fno-omit-frame-pointer \
-I$(JULIAHOME)/src -I$(JULIAHOME)/src/support -I$(build_includedir)
Expand Down

0 comments on commit c90c0af

Please sign in to comment.