From 0b411b873ca2691738d8ee3bd3c224ecc382ad64 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Sun, 1 Apr 2012 22:06:08 +0100 Subject: [PATCH 1/7] Separated compiler from the driver into the shared library --- CMakeLists.txt | 40 +++++++++++++++++++++++++++------------- {gen => driver}/main.cpp | 0 2 files changed, 27 insertions(+), 13 deletions(-) rename {gen => driver}/main.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ffd4ec7..4a5f6b82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,7 @@ foreach(TARGET ${HOST_ARCH} ${EXTRA_LLVM_MODULES}) endforeach(TARGET) set_source_files_properties( - ${PROJECT_SOURCE_DIR}/gen/main.cpp PROPERTIES + ${PROJECT_SOURCE_DIR}/driver/main.cpp PROPERTIES COMPILE_DEFINITIONS LDC_TARGETS=${LLVM_MODULES_DEFINE} ) @@ -204,6 +204,7 @@ set_source_files_properties( file(GLOB_RECURSE FE_SRC ${DMDFE_PATH}/*.c ${DMDFE_PATH}/*.h) file(GLOB_RECURSE GEN_SRC gen/*.cpp gen/*.h) file(GLOB IR_SRC ir/*.cpp ir/*.h) +file(GLOB_RECURSE DRV_SRC driver/*.cpp driver/*.h) # exclude idgen and impcnvgen and generated sources, just in case list(REMOVE_ITEM FE_SRC ${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/idgen.c @@ -266,9 +267,31 @@ endif(USE_METADATA) # # Set up the main ldc/ldc2 target. # +set(LDC_LIB LDCShared) # Path where ldc executable will be put -add_executable(${LDC_EXE} ${LDC_SOURCE_FILES}) +add_library(${LDC_LIB} SHARED ${LDC_SOURCE_FILES}) +# Build ldc +set_target_properties( + ${LDC_LIB} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" +) + +# LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems +target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}" ${LIBCONFIG_LDFLAGS} config++) +if(WIN32) + target_link_libraries(${LDC_LIB} imagehlp psapi) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + target_link_libraries(${LDC_LIB} dl) +endif(WIN32) + +if(USE_BOEHM_GC) + target_link_libraries(${LDC_LIB} ${PROJECT_SOURCE_DIR}/libgc.a) +endif(USE_BOEHM_GC) + +add_executable(${LDC_EXE} ${DRV_SRC}) # Name of ldc executable set(LDC_EXE_NAME ${PROGRAM_PREFIX}${LDC_EXE}${PROGRAM_SUFFIX}) # Build ldc @@ -278,18 +301,8 @@ set_target_properties( RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" ) +target_link_libraries(${LDC_EXE} ${LDC_LIB}) -# LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems -target_link_libraries(${LDC_EXE} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}" ${LIBCONFIG_LDFLAGS} config++) -if(WIN32) - target_link_libraries(${LDC_EXE} imagehlp psapi) -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - target_link_libraries(${LDC_EXE} dl) -endif(WIN32) - -if(USE_BOEHM_GC) - target_link_libraries(${LDC_EXE} ${PROJECT_SOURCE_DIR}/libgc.a) -endif(USE_BOEHM_GC) get_target_property(LDC_LOC ${LDC_EXE} LOCATION) @@ -300,6 +313,7 @@ get_target_property(LDC_LOC ${LDC_EXE} LOCATION) add_subdirectory(runtime) install(TARGETS ${LDC_EXE} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ${LDC_LIB} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install(PROGRAMS ${PROJECT_SOURCE_DIR}/bin/${LDMD_EXE} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}_install.conf DESTINATION ${CONF_INST_DIR} RENAME ${LDC_EXE}.conf) install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}_install.rebuild.conf DESTINATION ${CONF_INST_DIR} RENAME ${LDC_EXE}.rebuild.conf) diff --git a/gen/main.cpp b/driver/main.cpp similarity index 100% rename from gen/main.cpp rename to driver/main.cpp From 71044056e4465039eeb45940f7bf95d603ae447b Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Mon, 2 Apr 2012 00:11:30 +0100 Subject: [PATCH 2/7] split toobj.cpp and moved writeModule outside of LDCShared --- driver/main.cpp | 3 +- driver/toobj.cpp | 175 ++++ {gen => driver}/toobj.h | 0 gen/{toobj.cpp => module.cpp} | 1524 +++++++++++++++------------------ 4 files changed, 854 insertions(+), 848 deletions(-) create mode 100644 driver/toobj.cpp rename {gen => driver}/toobj.h (100%) rename gen/{toobj.cpp => module.cpp} (76%) diff --git a/driver/main.cpp b/driver/main.cpp index 3ff361e0..50f8ba03 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -33,7 +33,6 @@ #include "gen/linker.h" #include "gen/irstate.h" #include "gen/optimizer.h" -#include "gen/toobj.h" #include "gen/metadata.h" #include "gen/passes/Passes.h" @@ -43,6 +42,8 @@ using namespace opts; #include "gen/configfile.h" +#include "driver/toobj.h" + #if POSIX #include #elif _WIN32 diff --git a/driver/toobj.cpp b/driver/toobj.cpp new file mode 100644 index 00000000..98ce6abc --- /dev/null +++ b/driver/toobj.cpp @@ -0,0 +1,175 @@ + +// Copyright (c) 1999-2004 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include +#include + +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetMachine.h" + +#include "gen/irstate.h" +#include "gen/logger.h" +#include "gen/optimizer.h" + + +////////////////////////////////////////////////////////////////////////////////////////// + +extern llvm::cl::opt noVerify; + +////////////////////////////////////////////////////////////////////////////////////////// + +// fwd decl +void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out, + llvm::TargetMachine::CodeGenFileType fileType); + +////////////////////////////////////////////////////////////////////////////////////////// + +void writeModule(llvm::Module* m, std::string filename) +{ + // run optimizer + bool reverify = ldc_optimize_module(m); + + // verify the llvm + if (!noVerify && reverify) { + std::string verifyErr; + Logger::println("Verifying module... again..."); + LOG_SCOPE; + if (llvm::verifyModule(*m,llvm::ReturnStatusAction,&verifyErr)) + { + error("%s", verifyErr.c_str()); + fatal(); + } + else { + Logger::println("Verification passed!"); + } + } + + // eventually do our own path stuff, dmd's is a bit strange. + typedef llvm::sys::Path LLPath; + + // write LLVM bitcode + if (global.params.output_bc) { + LLPath bcpath = LLPath(filename); + bcpath.eraseSuffix(); + bcpath.appendSuffix(std::string(global.bc_ext)); + Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); + std::string errinfo; + llvm::raw_fd_ostream bos(bcpath.c_str(), errinfo, llvm::raw_fd_ostream::F_Binary); + if (bos.has_error()) + { + error("cannot write LLVM bitcode file '%s': %s", bcpath.c_str(), errinfo.c_str()); + fatal(); + } + llvm::WriteBitcodeToFile(m, bos); + } + + // write LLVM IR + if (global.params.output_ll) { + LLPath llpath = LLPath(filename); + llpath.eraseSuffix(); + llpath.appendSuffix(std::string(global.ll_ext)); + Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); + std::string errinfo; + llvm::raw_fd_ostream aos(llpath.c_str(), errinfo); + if (aos.has_error()) + { + error("cannot write LLVM asm file '%s': %s", llpath.c_str(), errinfo.c_str()); + fatal(); + } + m->print(aos, NULL); + } + + // write native assembly + if (global.params.output_s) { + LLPath spath = LLPath(filename); + spath.eraseSuffix(); + spath.appendSuffix(std::string(global.s_ext)); + Logger::println("Writing native asm to: %s\n", spath.c_str()); + std::string err; + { + llvm::raw_fd_ostream out(spath.c_str(), err); + if (err.empty()) + { + emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_AssemblyFile); + } + else + { + error("cannot write native asm: %s", err.c_str()); + fatal(); + } + } + } + + if (global.params.output_o) { + LLPath objpath = LLPath(filename); + Logger::println("Writing object file to: %s\n", objpath.c_str()); + std::string err; + { + llvm::raw_fd_ostream out(objpath.c_str(), err, llvm::raw_fd_ostream::F_Binary); + if (err.empty()) + { + emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_ObjectFile); + } + else + { + error("cannot write object file: %s", err.c_str()); + fatal(); + } + } + } +} + +/* ================================================================== */ + +// based on llc code, University of Illinois Open Source License +void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out, + llvm::TargetMachine::CodeGenFileType fileType) +{ + using namespace llvm; + + // Build up all of the passes that we want to do to the module. + FunctionPassManager Passes(&m); + + if (const TargetData *TD = Target.getTargetData()) + Passes.add(new TargetData(*TD)); + else + Passes.add(new TargetData(&m)); + + // Last argument is enum CodeGenOpt::Level OptLevel + // debug info doesn't work properly with OptLevel != None! + CodeGenOpt::Level LastArg = CodeGenOpt::Default; + if (global.params.symdebug || !optimize()) + LastArg = CodeGenOpt::None; + else if (optLevel() >= 3) + LastArg = CodeGenOpt::Aggressive; + + llvm::formatted_raw_ostream fout(out); + if (Target.addPassesToEmitFile(Passes, fout, fileType, LastArg)) + assert(0 && "no support for asm output"); + + Passes.doInitialization(); + + // Run our queue of passes all at once now, efficiently. + for (llvm::Module::iterator I = m.begin(), E = m.end(); I != E; ++I) + if (!I->isDeclaration()) + Passes.run(*I); + + Passes.doFinalization(); + + // release module from module provider so we can delete it ourselves + //std::string Err; + //llvm::Module* rmod = Provider.releaseModule(&Err); + //assert(rmod); +} diff --git a/gen/toobj.h b/driver/toobj.h similarity index 100% rename from gen/toobj.h rename to driver/toobj.h diff --git a/gen/toobj.cpp b/gen/module.cpp similarity index 76% rename from gen/toobj.cpp rename to gen/module.cpp index 1bc4929f..e17d35ee 100644 --- a/gen/toobj.cpp +++ b/gen/module.cpp @@ -1,847 +1,677 @@ - -// Copyright (c) 1999-2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include - -#include "gen/llvm.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/LinkAllPasses.h" -#include "llvm/Support/Program.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/LLVMContext.h" - -#include "mars.h" -#include "module.h" -#include "mtype.h" -#include "declaration.h" -#include "statement.h" -#include "enum.h" -#include "aggregate.h" -#include "init.h" -#include "attrib.h" -#include "id.h" -#include "import.h" -#include "template.h" -#include "scope.h" - -#include "gen/abi.h" -#include "gen/arrays.h" -#include "gen/classes.h" -#include "gen/cl_options.h" -#include "gen/functions.h" -#include "gen/irstate.h" -#include "gen/llvmhelpers.h" -#include "gen/logger.h" -#include "gen/optimizer.h" -#include "gen/programs.h" -#include "gen/rttibuilder.h" -#include "gen/runtime.h" -#include "gen/structs.h" -#include "gen/todebug.h" -#include "gen/tollvm.h" - -#include "ir/irvar.h" -#include "ir/irmodule.h" -#include "ir/irtype.h" - -#if DMDV2 -#define NEW_MODULEINFO_LAYOUT 1 -#endif - -////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::cl::opt noVerify("noverify", - llvm::cl::desc("Do not run the validation pass before writing bitcode"), - llvm::cl::ZeroOrMore); - -////////////////////////////////////////////////////////////////////////////////////////// - -// fwd decl -void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out, - llvm::TargetMachine::CodeGenFileType fileType); - -////////////////////////////////////////////////////////////////////////////////////////// - -llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) -{ - bool logenabled = Logger::enabled(); - if (llvmForceLogging && !logenabled) - { - Logger::enable(); - } - - Logger::println("Generating module: %s\n", (md ? md->toChars() : toChars())); - LOG_SCOPE; - - if (global.params.verbose_cg) - printf("codegen: %s (%s)\n", toPrettyChars(), srcfile->toChars()); - - assert(!global.errors); - - // name the module - llvm::StringRef mname(toChars()); - if (md != 0) - mname = md->toChars(); - - // create a new ir state - // TODO look at making the instance static and moving most functionality into IrModule where it belongs - IRState ir(new llvm::Module(mname, context)); - gIR = &ir; - ir.dmodule = this; - - // reset all IR data stored in Dsymbols - IrDsymbol::resetAll(); - - sir->setState(&ir); - - // set target triple - ir.module->setTargetTriple(global.params.targetTriple); - - // set final data layout - ir.module->setDataLayout(global.params.dataLayout); - if (Logger::enabled()) - Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n'; - - // allocate the target abi - gABI = TargetABI::getTarget(); - - // debug info - DtoDwarfCompileUnit(this); - - // handle invalid 'objectø module - if (!ClassDeclaration::object) { - error("is missing 'class Object'"); - fatal(); - } - if (!ClassDeclaration::classinfo) { - error("is missing 'class ClassInfo'"); - fatal(); - } - - LLVM_D_InitRuntime(); - - // process module members - for (unsigned k=0; k < members->dim; k++) { - Dsymbol* dsym = (Dsymbol*)(members->data[k]); - assert(dsym); - dsym->codegen(sir); - } - - // emit function bodies - sir->emitFunctionBodies(); - - // for singleobj-compilation, fully emit all seen template instances - if (opts::singleObj) - { - while (!ir.seenTemplateInstances.empty()) - { - IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end(); - for (it = ir.seenTemplateInstances.begin(); it != end; ++it) - (*it)->codegen(sir); - ir.seenTemplateInstances.clear(); - - // emit any newly added function bodies - sir->emitFunctionBodies(); - } - } - - // finilize debug info - DtoDwarfModuleEnd(); - - // generate ModuleInfo - genmoduleinfo(); - - // verify the llvm - if (!noVerify) { - std::string verifyErr; - Logger::println("Verifying module..."); - LOG_SCOPE; - if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) - { - error("%s", verifyErr.c_str()); - fatal(); - } - else { - Logger::println("Verification passed!"); - } - } - - gIR = NULL; - - if (llvmForceLogging && !logenabled) - { - Logger::disable(); - } - - sir->setState(NULL); - - return ir.module; -} - -void writeModule(llvm::Module* m, std::string filename) -{ - // run optimizer - bool reverify = ldc_optimize_module(m); - - // verify the llvm - if (!noVerify && reverify) { - std::string verifyErr; - Logger::println("Verifying module... again..."); - LOG_SCOPE; - if (llvm::verifyModule(*m,llvm::ReturnStatusAction,&verifyErr)) - { - error("%s", verifyErr.c_str()); - fatal(); - } - else { - Logger::println("Verification passed!"); - } - } - - // eventually do our own path stuff, dmd's is a bit strange. - typedef llvm::sys::Path LLPath; - - // write LLVM bitcode - if (global.params.output_bc) { - LLPath bcpath = LLPath(filename); - bcpath.eraseSuffix(); - bcpath.appendSuffix(std::string(global.bc_ext)); - Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); - std::string errinfo; - llvm::raw_fd_ostream bos(bcpath.c_str(), errinfo, llvm::raw_fd_ostream::F_Binary); - if (bos.has_error()) - { - error("cannot write LLVM bitcode file '%s': %s", bcpath.c_str(), errinfo.c_str()); - fatal(); - } - llvm::WriteBitcodeToFile(m, bos); - } - - // write LLVM IR - if (global.params.output_ll) { - LLPath llpath = LLPath(filename); - llpath.eraseSuffix(); - llpath.appendSuffix(std::string(global.ll_ext)); - Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); - std::string errinfo; - llvm::raw_fd_ostream aos(llpath.c_str(), errinfo); - if (aos.has_error()) - { - error("cannot write LLVM asm file '%s': %s", llpath.c_str(), errinfo.c_str()); - fatal(); - } - m->print(aos, NULL); - } - - // write native assembly - if (global.params.output_s) { - LLPath spath = LLPath(filename); - spath.eraseSuffix(); - spath.appendSuffix(std::string(global.s_ext)); - Logger::println("Writing native asm to: %s\n", spath.c_str()); - std::string err; - { - llvm::raw_fd_ostream out(spath.c_str(), err); - if (err.empty()) - { - emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_AssemblyFile); - } - else - { - error("cannot write native asm: %s", err.c_str()); - fatal(); - } - } - } - - if (global.params.output_o) { - LLPath objpath = LLPath(filename); - Logger::println("Writing object file to: %s\n", objpath.c_str()); - std::string err; - { - llvm::raw_fd_ostream out(objpath.c_str(), err, llvm::raw_fd_ostream::F_Binary); - if (err.empty()) - { - emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_ObjectFile); - } - else - { - error("cannot write object file: %s", err.c_str()); - fatal(); - } - } - } -} - -/* ================================================================== */ - -// based on llc code, University of Illinois Open Source License -void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out, - llvm::TargetMachine::CodeGenFileType fileType) -{ - using namespace llvm; - - // Build up all of the passes that we want to do to the module. - FunctionPassManager Passes(&m); - - if (const TargetData *TD = Target.getTargetData()) - Passes.add(new TargetData(*TD)); - else - Passes.add(new TargetData(&m)); - - // Last argument is enum CodeGenOpt::Level OptLevel - // debug info doesn't work properly with OptLevel != None! - CodeGenOpt::Level LastArg = CodeGenOpt::Default; - if (global.params.symdebug || !optimize()) - LastArg = CodeGenOpt::None; - else if (optLevel() >= 3) - LastArg = CodeGenOpt::Aggressive; - - llvm::formatted_raw_ostream fout(out); - if (Target.addPassesToEmitFile(Passes, fout, fileType, LastArg)) - assert(0 && "no support for asm output"); - - Passes.doInitialization(); - - // Run our queue of passes all at once now, efficiently. - for (llvm::Module::iterator I = m.begin(), E = m.end(); I != E; ++I) - if (!I->isDeclaration()) - Passes.run(*I); - - Passes.doFinalization(); - - // release module from module provider so we can delete it ourselves - //std::string Err; - //llvm::Module* rmod = Provider.releaseModule(&Err); - //assert(rmod); -} - -/* ================================================================== */ - -static llvm::Function* build_module_function(const std::string &name, const std::list &funcs, - const std::list &gates = std::list()) -{ - if (gates.empty()) { - if (funcs.empty()) - return NULL; - - if (funcs.size() == 1) - return funcs.front()->ir.irFunc->func; - } - - std::vector argsTy; - LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false); - assert(gIR->module->getFunction(name) == NULL); - llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); - fn->setCallingConv(DtoCallingConv(0, LINKd)); - - llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); - IRBuilder<> builder(bb); - - // debug info - DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); - - // Call ctor's - typedef std::list::const_iterator FuncIterator; - for (FuncIterator itr = funcs.begin(), end = funcs.end(); itr != end; ++itr) { - llvm::Function* f = (*itr)->ir.irFunc->func; - llvm::CallInst* call = builder.CreateCall(f,""); - call->setCallingConv(DtoCallingConv(0, LINKd)); - } - - // Increment vgate's - typedef std::list::const_iterator GatesIterator; - for (GatesIterator itr = gates.begin(), end = gates.end(); itr != end; ++itr) { - assert((*itr)->ir.irGlobal); - llvm::Value* val = (*itr)->ir.irGlobal->value; - llvm::Value* rval = builder.CreateLoad(val, "vgate"); - llvm::Value* res = builder.CreateAdd(rval, DtoConstUint(1), "vgate"); - builder.CreateStore(res, val); - } - - builder.CreateRetVoid(); - return fn; -} - -// build module ctor - -llvm::Function* build_module_ctor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("6__ctorZ"); -#if DMDV2 - return build_module_function(name, gIR->ctors, gIR->gates); -#else - return build_module_function(name, gIR->ctors); -#endif -} - -// build module dtor - -static llvm::Function* build_module_dtor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("6__dtorZ"); - return build_module_function(name, gIR->dtors); -} - -// build module unittest - -static llvm::Function* build_module_unittest() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("10__unittestZ"); - return build_module_function(name, gIR->unitTests); -} - -#if DMDV2 - -// build module shared ctor - -llvm::Function* build_module_shared_ctor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("13__shared_ctorZ"); - return build_module_function(name, gIR->sharedCtors, gIR->sharedGates); -} - -// build module shared dtor - -static llvm::Function* build_module_shared_dtor() -{ - std::string name("_D"); - name.append(gIR->dmodule->mangle()); - name.append("13__shared_dtorZ"); - return build_module_function(name, gIR->sharedDtors); -} - -#endif - -// build ModuleReference and register function, to register the module info in the global linked list -static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) -{ - // build ctor type - LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); - - // build ctor name - std::string fname = "_D"; - fname += gIR->dmodule->mangle(); - fname += "16__moduleinfoCtorZ"; - - // build a function that registers the moduleinfo in the global moduleinfo linked list - LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module); - - // provide the default initializer - LLStructType* modulerefTy = DtoModuleReferenceType(); - std::vector mrefvalues; - mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0))); - mrefvalues.push_back(llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1))); - LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues); - - // create the ModuleReference node for this module - std::string thismrefname = "_D"; - thismrefname += gIR->dmodule->mangle(); - thismrefname += "11__moduleRefZ"; - LLGlobalVariable* thismref = new LLGlobalVariable(*gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname); - - // make sure _Dmodule_ref is declared - LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref"); - LLType *modulerefPtrTy = getPtrToType(modulerefTy); - if (!mref) - mref = new LLGlobalVariable(*gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref"); - mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy)); - - // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list - llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor); - IRBuilder<> builder(bb); - - // debug info - llvm::DISubprogram subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); - - // get current beginning - LLValue* curbeg = builder.CreateLoad(mref, "current"); - - // put current beginning as the next of this one - LLValue* gep = builder.CreateStructGEP(thismref, 0, "next"); - builder.CreateStore(curbeg, gep); - - // replace beginning - builder.CreateStore(thismref, mref); - - // return - builder.CreateRetVoid(); - - return ctor; -} - -llvm::GlobalVariable* Module::moduleInfoSymbol() -{ - // create name - std::string MIname("_D"); - MIname.append(mangle()); - MIname.append("8__ModuleZ"); - - if (gIR->dmodule != this) { - LLType* moduleinfoTy = DtoType(moduleinfo->type); - LLGlobalVariable *var = gIR->module->getGlobalVariable(MIname); - if (!var) - var = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); - return var; - } - - if (moduleInfoVar) - return moduleInfoVar; - - // declare global - // flags will be modified at runtime so can't make it constant - moduleInfoVar = new llvm::GlobalVariable(*gIR->module, moduleInfoType, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); - - return moduleInfoVar; -} - -// Put out instance of ModuleInfo for this Module - -void Module::genmoduleinfo() -{ - // resolve ModuleInfo - if (!moduleinfo) - { - error("object.d is missing the ModuleInfo class"); - fatal(); - } - // check for patch - else - { -#if DMDV2 - unsigned sizeof_ModuleInfo = 16 * PTRSIZE; -#else - unsigned sizeof_ModuleInfo = 14 * PTRSIZE; -#endif - if (sizeof_ModuleInfo != moduleinfo->structsize) - { - error("object.d ModuleInfo class is incorrect"); - fatal(); - } - } - - // use the RTTIBuilder - RTTIBuilder b(moduleinfo); - - // some types - LLType* moduleinfoTy = moduleinfo->type->irtype->getType(); - LLType* classinfoTy = ClassDeclaration::classinfo->type->irtype->getType(); - - // importedModules[] - std::vector importInits; - LLConstant* importedModules = 0; - llvm::ArrayType* importedModulesTy = 0; - for (size_t i = 0; i < aimports.dim; i++) - { - Module *m = (Module *)aimports.data[i]; - if (!m->needModuleInfo() || m == this) - continue; - - // declare the imported module info - std::string m_name("_D"); - m_name.append(m->mangle()); - m_name.append("8__ModuleZ"); - llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); - if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name); - importInits.push_back(m_gvar); - } - // has import array? - if (!importInits.empty()) - { - importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size()); - importedModules = LLConstantArray::get(importedModulesTy, importInits); - } - - // localClasses[] - LLConstant* localClasses = 0; - llvm::ArrayType* localClassesTy = 0; - ClassDeclarations aclasses; - //printf("members->dim = %d\n", members->dim); - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *member; - - member = (Dsymbol *)members->data[i]; - //printf("\tmember '%s'\n", member->toChars()); - member->addLocalClass(&aclasses); - } - // fill inits - std::vector classInits; - for (size_t i = 0; i < aclasses.dim; i++) - { - ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i]; - cd->codegen(Type::sir); - - if (cd->isInterfaceDeclaration()) - { - Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars()); - continue; - } - else if (cd->sizeok != 1) - { - Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars()); - continue; - } - Logger::println("class: %s", cd->toPrettyChars()); - LLConstant *c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy)); - classInits.push_back(c); - } - // has class array? - if (!classInits.empty()) - { - localClassesTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size()); - localClasses = LLConstantArray::get(localClassesTy, classInits); - } - -#if NEW_MODULEINFO_LAYOUT - - // These must match the values in druntime/src/object_.d - #define MIstandalone 4 - #define MItlsctor 8 - #define MItlsdtor 0x10 - #define MIctor 0x20 - #define MIdtor 0x40 - #define MIxgetMembers 0x80 - #define MIictor 0x100 - #define MIunitTest 0x200 - #define MIimportedModules 0x400 - #define MIlocalClasses 0x800 - #define MInew 0x80000000 // it's the "new" layout - - llvm::Function* fsharedctor = build_module_shared_ctor(); - llvm::Function* fshareddtor = build_module_shared_dtor(); - llvm::Function* funittest = build_module_unittest(); - llvm::Function* fctor = build_module_ctor(); - llvm::Function* fdtor = build_module_dtor(); - - unsigned flags = MInew; - if (fctor) - flags |= MItlsctor; - if (fdtor) - flags |= MItlsdtor; - if (fsharedctor) - flags |= MIctor; - if (fshareddtor) - flags |= MIdtor; -#if 0 - if (fgetmembers) - flags |= MIxgetMembers; - if (fictor) - flags |= MIictor; -#endif - if (funittest) - flags |= MIunitTest; - if (importedModules) - flags |= MIimportedModules; - if (localClasses) - flags |= MIlocalClasses; - - if (!needmoduleinfo) - flags |= MIstandalone; - - b.push_uint(flags); // flags - b.push_uint(0); // index - - if (fctor) - b.push(fctor); - if (fdtor) - b.push(fdtor); - if (fsharedctor) - b.push(fsharedctor); - if (fshareddtor) - b.push(fshareddtor); -#if 0 - if (fgetmembers) - b.push(fgetmembers); - if (fictor) - b.push(fictor); -#endif - if (funittest) - b.push(funittest); - if (importedModules) { - b.push_size(importInits.size()); - b.push(importedModules); - } - if (localClasses) { - b.push_size(classInits.size()); - b.push(localClasses); - } - - // Put out module name as a 0-terminated string, to save bytes - b.push(DtoConstStringPtr(toPrettyChars())); - -#else - // The layout is: - // char[] name; - // ModuleInfo[] importedModules; - // ClassInfo[] localClasses; - // uint flags; - // - // void function() ctor; - // void function() dtor; - // void function() unitTest; - // - // void* xgetMembers; - // void function() ictor; - // - // version(D_Version2) { - // void *sharedctor; - // void *shareddtor; - // uint index; - // void*[1] reserved; - // } - - LLConstant *c = 0; - - // name - b.push_string(toPrettyChars()); - - // importedModules - if (importedModules) - { - std::string m_name("_D"); - m_name.append(mangle()); - m_name.append("9__importsZ"); - llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); - if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, importedModulesTy, true, llvm::GlobalValue::InternalLinkage, importedModules, m_name); - c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importedModulesTy->getElementType())); - c = DtoConstSlice(DtoConstSize_t(importInits.size()), c); - } - else - { - c = DtoConstSlice(DtoConstSize_t(0), getNullValue(getPtrToType(moduleinfoTy))); - } - b.push(c); - - // localClasses - if (localClasses) - { - std::string m_name("_D"); - m_name.append(mangle()); - m_name.append("9__classesZ"); - assert(gIR->module->getGlobalVariable(m_name) == NULL); - llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(*gIR->module, localClassesTy, true, llvm::GlobalValue::InternalLinkage, localClasses, m_name); - c = DtoGEPi(m_gvar, 0, 0); - c = DtoConstSlice(DtoConstSize_t(classInits.size()), c); - } - else - { - c = DtoConstSlice( DtoConstSize_t(0), getNullValue(getPtrToType(getPtrToType(classinfoTy))) ); - } - b.push(c); - - // flags (4 means MIstandalone) - unsigned mi_flags = needmoduleinfo ? 0 : 4; - b.push_uint(mi_flags); - - // function pointer type for next three fields - LLType* fnptrTy = getPtrToType(LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false)); - - // ctor -#if DMDV2 - llvm::Function* fctor = build_module_shared_ctor(); -#else - llvm::Function* fctor = build_module_ctor(); -#endif - c = fctor ? fctor : getNullValue(fnptrTy); - b.push(c); - - // dtor -#if DMDV2 - llvm::Function* fdtor = build_module_shared_dtor(); -#else - llvm::Function* fdtor = build_module_dtor(); -#endif - c = fdtor ? fdtor : getNullValue(fnptrTy); - b.push(c); - - // unitTest - llvm::Function* unittest = build_module_unittest(); - c = unittest ? unittest : getNullValue(fnptrTy); - b.push(c); - - // xgetMembers - c = getNullValue(getVoidPtrType()); - b.push(c); - - // ictor - c = getNullValue(fnptrTy); - b.push(c); - -#if DMDV2 - - // tls ctor - fctor = build_module_ctor(); - c = fctor ? fctor : getNullValue(fnptrTy); - b.push(c); - - // tls dtor - fdtor = build_module_dtor(); - c = fdtor ? fdtor : getNullValue(fnptrTy); - b.push(c); - - // index + reserved void*[1] - LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 2); - c = getNullValue(AT); - b.push(c); - -#endif - -#endif - - /*Logger::println("MODULE INFO INITIALIZERS"); - for (size_t i=0; igetType() != moduleinfoTy->getElementType(i)) - assert(0); - }*/ - - // create and set initializer - b.finalize(moduleInfoType, moduleInfoSymbol()); - - // build the modulereference and ctor for registering it - LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSymbol()); - - // register this ctor in the magic llvm.global_ctors appending array - LLFunctionType* magicfty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); - std::vector magictypes; - magictypes.push_back(LLType::getInt32Ty(gIR->context())); - magictypes.push_back(getPtrToType(magicfty)); - LLStructType* magicsty = LLStructType::get(gIR->context(), magictypes); - - // make the constant element - std::vector magicconstants; - magicconstants.push_back(DtoConstUint(65535)); - magicconstants.push_back(mictor); - LLConstant* magicinit = LLConstantStruct::get(magicsty, magicconstants); - - // declare the appending array - llvm::ArrayType* appendArrTy = llvm::ArrayType::get(magicsty, 1); - std::vector appendInits(1, magicinit); - LLConstant* appendInit = LLConstantArray::get(appendArrTy, appendInits); - std::string appendName("llvm.global_ctors"); - new llvm::GlobalVariable(*gIR->module, appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName); -} +#include "gen/llvm.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Module.h" +#include "llvm/LinkAllPasses.h" + +#include "mars.h" +#include "module.h" +#include "mtype.h" +#include "declaration.h" +#include "statement.h" +#include "enum.h" +#include "aggregate.h" +#include "init.h" +#include "attrib.h" +#include "id.h" +#include "import.h" +#include "template.h" +#include "scope.h" + +#include "gen/abi.h" +#include "gen/arrays.h" +#include "gen/classes.h" +#include "gen/cl_options.h" +#include "gen/functions.h" +#include "gen/llvmhelpers.h" +#include "gen/logger.h" +#include "gen/programs.h" +#include "gen/rttibuilder.h" +#include "gen/runtime.h" +#include "gen/structs.h" +#include "gen/todebug.h" +#include "gen/tollvm.h" + +#include "ir/irvar.h" +#include "ir/irmodule.h" +#include "ir/irtype.h" + +#if DMDV2 +#define NEW_MODULEINFO_LAYOUT 1 +#endif + +////////////////////////////////////////////////////////////////////////////////////////// + +llvm::cl::opt noVerify("noverify", + llvm::cl::desc("Do not run the validation pass before writing bitcode"), + llvm::cl::ZeroOrMore); + +////////////////////////////////////////////////////////////////////////////////////////// + +static llvm::Function* build_module_function(const std::string &name, const std::list &funcs, + const std::list &gates = std::list()) +{ + if (gates.empty()) { + if (funcs.empty()) + return NULL; + + if (funcs.size() == 1) + return funcs.front()->ir.irFunc->func; + } + + std::vector argsTy; + LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false); + assert(gIR->module->getFunction(name) == NULL); + llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); + fn->setCallingConv(DtoCallingConv(0, LINKd)); + + llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); + IRBuilder<> builder(bb); + + // debug info + DtoDwarfSubProgramInternal(name.c_str(), name.c_str()); + + // Call ctor's + typedef std::list::const_iterator FuncIterator; + for (FuncIterator itr = funcs.begin(), end = funcs.end(); itr != end; ++itr) { + llvm::Function* f = (*itr)->ir.irFunc->func; + llvm::CallInst* call = builder.CreateCall(f,""); + call->setCallingConv(DtoCallingConv(0, LINKd)); + } + + // Increment vgate's + typedef std::list::const_iterator GatesIterator; + for (GatesIterator itr = gates.begin(), end = gates.end(); itr != end; ++itr) { + assert((*itr)->ir.irGlobal); + llvm::Value* val = (*itr)->ir.irGlobal->value; + llvm::Value* rval = builder.CreateLoad(val, "vgate"); + llvm::Value* res = builder.CreateAdd(rval, DtoConstUint(1), "vgate"); + builder.CreateStore(res, val); + } + + builder.CreateRetVoid(); + return fn; +} + +// build module ctor + +llvm::Function* build_module_ctor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("6__ctorZ"); +#if DMDV2 + return build_module_function(name, gIR->ctors, gIR->gates); +#else + return build_module_function(name, gIR->ctors); +#endif +} + +// build module dtor + +static llvm::Function* build_module_dtor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("6__dtorZ"); + return build_module_function(name, gIR->dtors); +} + +// build module unittest + +static llvm::Function* build_module_unittest() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("10__unittestZ"); + return build_module_function(name, gIR->unitTests); +} + +#if DMDV2 + +// build module shared ctor + +llvm::Function* build_module_shared_ctor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("13__shared_ctorZ"); + return build_module_function(name, gIR->sharedCtors, gIR->sharedGates); +} + +// build module shared dtor + +static llvm::Function* build_module_shared_dtor() +{ + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("13__shared_dtorZ"); + return build_module_function(name, gIR->sharedDtors); +} + +#endif + +// build ModuleReference and register function, to register the module info in the global linked list +static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) +{ + // build ctor type + LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); + + // build ctor name + std::string fname = "_D"; + fname += gIR->dmodule->mangle(); + fname += "16__moduleinfoCtorZ"; + + // build a function that registers the moduleinfo in the global moduleinfo linked list + LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module); + + // provide the default initializer + LLStructType* modulerefTy = DtoModuleReferenceType(); + std::vector mrefvalues; + mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0))); + mrefvalues.push_back(llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1))); + LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues); + + // create the ModuleReference node for this module + std::string thismrefname = "_D"; + thismrefname += gIR->dmodule->mangle(); + thismrefname += "11__moduleRefZ"; + LLGlobalVariable* thismref = new LLGlobalVariable(*gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname); + + // make sure _Dmodule_ref is declared + LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref"); + LLType *modulerefPtrTy = getPtrToType(modulerefTy); + if (!mref) + mref = new LLGlobalVariable(*gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref"); + mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy)); + + // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list + llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor); + IRBuilder<> builder(bb); + + // debug info + llvm::DISubprogram subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); + + // get current beginning + LLValue* curbeg = builder.CreateLoad(mref, "current"); + + // put current beginning as the next of this one + LLValue* gep = builder.CreateStructGEP(thismref, 0, "next"); + builder.CreateStore(curbeg, gep); + + // replace beginning + builder.CreateStore(thismref, mref); + + // return + builder.CreateRetVoid(); + + return ctor; +} + +llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) +{ + bool logenabled = Logger::enabled(); + if (llvmForceLogging && !logenabled) + { + Logger::enable(); + } + + Logger::println("Generating module: %s\n", (md ? md->toChars() : toChars())); + LOG_SCOPE; + + if (global.params.verbose_cg) + printf("codegen: %s (%s)\n", toPrettyChars(), srcfile->toChars()); + + assert(!global.errors); + + // name the module + llvm::StringRef mname(toChars()); + if (md != 0) + mname = md->toChars(); + + // create a new ir state + // TODO look at making the instance static and moving most functionality into IrModule where it belongs + IRState ir(new llvm::Module(mname, context)); + gIR = &ir; + ir.dmodule = this; + + // reset all IR data stored in Dsymbols + IrDsymbol::resetAll(); + + sir->setState(&ir); + + // set target triple + ir.module->setTargetTriple(global.params.targetTriple); + + // set final data layout + ir.module->setDataLayout(global.params.dataLayout); + if (Logger::enabled()) + Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n'; + + // allocate the target abi + gABI = TargetABI::getTarget(); + + // debug info + DtoDwarfCompileUnit(this); + + // handle invalid 'objectø module + if (!ClassDeclaration::object) { + error("is missing 'class Object'"); + fatal(); + } + if (!ClassDeclaration::classinfo) { + error("is missing 'class ClassInfo'"); + fatal(); + } + + LLVM_D_InitRuntime(); + + // process module members + for (unsigned k=0; k < members->dim; k++) { + Dsymbol* dsym = (Dsymbol*)(members->data[k]); + assert(dsym); + dsym->codegen(sir); + } + + // emit function bodies + sir->emitFunctionBodies(); + + // for singleobj-compilation, fully emit all seen template instances + if (opts::singleObj) + { + while (!ir.seenTemplateInstances.empty()) + { + IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end(); + for (it = ir.seenTemplateInstances.begin(); it != end; ++it) + (*it)->codegen(sir); + ir.seenTemplateInstances.clear(); + + // emit any newly added function bodies + sir->emitFunctionBodies(); + } + } + + // finilize debug info + DtoDwarfModuleEnd(); + + // generate ModuleInfo + genmoduleinfo(); + + // verify the llvm + if (!noVerify) { + std::string verifyErr; + Logger::println("Verifying module..."); + LOG_SCOPE; + if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) + { + error("%s", verifyErr.c_str()); + fatal(); + } + else { + Logger::println("Verification passed!"); + } + } + + gIR = NULL; + + if (llvmForceLogging && !logenabled) + { + Logger::disable(); + } + + sir->setState(NULL); + + return ir.module; +} + +llvm::GlobalVariable* Module::moduleInfoSymbol() +{ + // create name + std::string MIname("_D"); + MIname.append(mangle()); + MIname.append("8__ModuleZ"); + + if (gIR->dmodule != this) { + LLType* moduleinfoTy = DtoType(moduleinfo->type); + LLGlobalVariable *var = gIR->module->getGlobalVariable(MIname); + if (!var) + var = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); + return var; + } + + if (moduleInfoVar) + return moduleInfoVar; + + // declare global + // flags will be modified at runtime so can't make it constant + moduleInfoVar = new llvm::GlobalVariable(*gIR->module, moduleInfoType, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); + + return moduleInfoVar; +} + +// Put out instance of ModuleInfo for this Module +void Module::genmoduleinfo() +{ + // resolve ModuleInfo + if (!moduleinfo) + { + error("object.d is missing the ModuleInfo class"); + fatal(); + } + // check for patch + else + { +#if DMDV2 + unsigned sizeof_ModuleInfo = 16 * PTRSIZE; +#else + unsigned sizeof_ModuleInfo = 14 * PTRSIZE; +#endif + if (sizeof_ModuleInfo != moduleinfo->structsize) + { + error("object.d ModuleInfo class is incorrect"); + fatal(); + } + } + + // use the RTTIBuilder + RTTIBuilder b(moduleinfo); + + // some types + LLType* moduleinfoTy = moduleinfo->type->irtype->getType(); + LLType* classinfoTy = ClassDeclaration::classinfo->type->irtype->getType(); + + // importedModules[] + std::vector importInits; + LLConstant* importedModules = 0; + llvm::ArrayType* importedModulesTy = 0; + for (size_t i = 0; i < aimports.dim; i++) + { + Module *m = (Module *)aimports.data[i]; + if (!m->needModuleInfo() || m == this) + continue; + + // declare the imported module info + std::string m_name("_D"); + m_name.append(m->mangle()); + m_name.append("8__ModuleZ"); + llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); + if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name); + importInits.push_back(m_gvar); + } + // has import array? + if (!importInits.empty()) + { + importedModulesTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size()); + importedModules = LLConstantArray::get(importedModulesTy, importInits); + } + + // localClasses[] + LLConstant* localClasses = 0; + llvm::ArrayType* localClassesTy = 0; + ClassDeclarations aclasses; + //printf("members->dim = %d\n", members->dim); + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *member; + + member = (Dsymbol *)members->data[i]; + //printf("\tmember '%s'\n", member->toChars()); + member->addLocalClass(&aclasses); + } + // fill inits + std::vector classInits; + for (size_t i = 0; i < aclasses.dim; i++) + { + ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i]; + cd->codegen(Type::sir); + + if (cd->isInterfaceDeclaration()) + { + Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars()); + continue; + } + else if (cd->sizeok != 1) + { + Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars()); + continue; + } + Logger::println("class: %s", cd->toPrettyChars()); + LLConstant *c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy)); + classInits.push_back(c); + } + // has class array? + if (!classInits.empty()) + { + localClassesTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size()); + localClasses = LLConstantArray::get(localClassesTy, classInits); + } + +#if NEW_MODULEINFO_LAYOUT + + // These must match the values in druntime/src/object_.d + #define MIstandalone 4 + #define MItlsctor 8 + #define MItlsdtor 0x10 + #define MIctor 0x20 + #define MIdtor 0x40 + #define MIxgetMembers 0x80 + #define MIictor 0x100 + #define MIunitTest 0x200 + #define MIimportedModules 0x400 + #define MIlocalClasses 0x800 + #define MInew 0x80000000 // it's the "new" layout + + llvm::Function* fsharedctor = build_module_shared_ctor(); + llvm::Function* fshareddtor = build_module_shared_dtor(); + llvm::Function* funittest = build_module_unittest(); + llvm::Function* fctor = build_module_ctor(); + llvm::Function* fdtor = build_module_dtor(); + + unsigned flags = MInew; + if (fctor) + flags |= MItlsctor; + if (fdtor) + flags |= MItlsdtor; + if (fsharedctor) + flags |= MIctor; + if (fshareddtor) + flags |= MIdtor; +#if 0 + if (fgetmembers) + flags |= MIxgetMembers; + if (fictor) + flags |= MIictor; +#endif + if (funittest) + flags |= MIunitTest; + if (importedModules) + flags |= MIimportedModules; + if (localClasses) + flags |= MIlocalClasses; + + if (!needmoduleinfo) + flags |= MIstandalone; + + b.push_uint(flags); // flags + b.push_uint(0); // index + + if (fctor) + b.push(fctor); + if (fdtor) + b.push(fdtor); + if (fsharedctor) + b.push(fsharedctor); + if (fshareddtor) + b.push(fshareddtor); +#if 0 + if (fgetmembers) + b.push(fgetmembers); + if (fictor) + b.push(fictor); +#endif + if (funittest) + b.push(funittest); + if (importedModules) { + b.push_size(importInits.size()); + b.push(importedModules); + } + if (localClasses) { + b.push_size(classInits.size()); + b.push(localClasses); + } + + // Put out module name as a 0-terminated string, to save bytes + b.push(DtoConstStringPtr(toPrettyChars())); + +#else + // The layout is: + // char[] name; + // ModuleInfo[] importedModules; + // ClassInfo[] localClasses; + // uint flags; + // + // void function() ctor; + // void function() dtor; + // void function() unitTest; + // + // void* xgetMembers; + // void function() ictor; + // + // version(D_Version2) { + // void *sharedctor; + // void *shareddtor; + // uint index; + // void*[1] reserved; + // } + + LLConstant *c = 0; + + // name + b.push_string(toPrettyChars()); + + // importedModules + if (importedModules) + { + std::string m_name("_D"); + m_name.append(mangle()); + m_name.append("9__importsZ"); + llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); + if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, importedModulesTy, true, llvm::GlobalValue::InternalLinkage, importedModules, m_name); + c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importedModulesTy->getElementType())); + c = DtoConstSlice(DtoConstSize_t(importInits.size()), c); + } + else + { + c = DtoConstSlice(DtoConstSize_t(0), getNullValue(getPtrToType(moduleinfoTy))); + } + b.push(c); + + // localClasses + if (localClasses) + { + std::string m_name("_D"); + m_name.append(mangle()); + m_name.append("9__classesZ"); + assert(gIR->module->getGlobalVariable(m_name) == NULL); + llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(*gIR->module, localClassesTy, true, llvm::GlobalValue::InternalLinkage, localClasses, m_name); + c = DtoGEPi(m_gvar, 0, 0); + c = DtoConstSlice(DtoConstSize_t(classInits.size()), c); + } + else + { + c = DtoConstSlice( DtoConstSize_t(0), getNullValue(getPtrToType(getPtrToType(classinfoTy))) ); + } + b.push(c); + + // flags (4 means MIstandalone) + unsigned mi_flags = needmoduleinfo ? 0 : 4; + b.push_uint(mi_flags); + + // function pointer type for next three fields + LLType* fnptrTy = getPtrToType(LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false)); + + // ctor +#if DMDV2 + llvm::Function* fctor = build_module_shared_ctor(); +#else + llvm::Function* fctor = build_module_ctor(); +#endif + c = fctor ? fctor : getNullValue(fnptrTy); + b.push(c); + + // dtor +#if DMDV2 + llvm::Function* fdtor = build_module_shared_dtor(); +#else + llvm::Function* fdtor = build_module_dtor(); +#endif + c = fdtor ? fdtor : getNullValue(fnptrTy); + b.push(c); + + // unitTest + llvm::Function* unittest = build_module_unittest(); + c = unittest ? unittest : getNullValue(fnptrTy); + b.push(c); + + // xgetMembers + c = getNullValue(getVoidPtrType()); + b.push(c); + + // ictor + c = getNullValue(fnptrTy); + b.push(c); + +#if DMDV2 + + // tls ctor + fctor = build_module_ctor(); + c = fctor ? fctor : getNullValue(fnptrTy); + b.push(c); + + // tls dtor + fdtor = build_module_dtor(); + c = fdtor ? fdtor : getNullValue(fnptrTy); + b.push(c); + + // index + reserved void*[1] + LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 2); + c = getNullValue(AT); + b.push(c); + +#endif + +#endif + + /*Logger::println("MODULE INFO INITIALIZERS"); + for (size_t i=0; igetType() != moduleinfoTy->getElementType(i)) + assert(0); + }*/ + + // create and set initializer + b.finalize(moduleInfoType, moduleInfoSymbol()); + + // build the modulereference and ctor for registering it + LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSymbol()); + + // register this ctor in the magic llvm.global_ctors appending array + LLFunctionType* magicfty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector(), false); + std::vector magictypes; + magictypes.push_back(LLType::getInt32Ty(gIR->context())); + magictypes.push_back(getPtrToType(magicfty)); + LLStructType* magicsty = LLStructType::get(gIR->context(), magictypes); + + // make the constant element + std::vector magicconstants; + magicconstants.push_back(DtoConstUint(65535)); + magicconstants.push_back(mictor); + LLConstant* magicinit = LLConstantStruct::get(magicsty, magicconstants); + + // declare the appending array + llvm::ArrayType* appendArrTy = llvm::ArrayType::get(magicsty, 1); + std::vector appendInits(1, magicinit); + LLConstant* appendInit = LLConstantArray::get(appendArrTy, appendInits); + std::string appendName("llvm.global_ctors"); + new llvm::GlobalVariable(*gIR->module, appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName); +} From feefad412c8ce7c73d753516483e74f4150fa881 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Mon, 2 Apr 2012 14:53:52 +0100 Subject: [PATCH 3/7] Move cl_options out of LDCShared --- dmd2/mars.h | 5 +++++ {gen => driver}/cl_options.cpp | 14 +++++++++----- {gen => driver}/cl_options.h | 4 ++-- {gen => driver}/linker.cpp | 5 +++-- {gen => driver}/linker.h | 0 driver/main.cpp | 4 ++-- driver/toobj.cpp | 8 +------- gen/arrays.cpp | 2 -- gen/functions.cpp | 3 +-- gen/linkage.cpp | 1 - gen/llvmhelpers.cpp | 3 +-- gen/module.cpp | 12 ++---------- 12 files changed, 26 insertions(+), 35 deletions(-) rename {gen => driver}/cl_options.cpp (96%) rename {gen => driver}/cl_options.h (95%) rename {gen => driver}/linker.cpp (99%) rename {gen => driver}/linker.h (100%) diff --git a/dmd2/mars.h b/dmd2/mars.h index dc640308..81d42059 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -272,6 +272,11 @@ struct Param const char* llvmArch; const char *targetTriple; const char *dataLayout; + + // Codegen cl options + bool singleObj; + bool disableRedZone; + bool noVerify; #endif }; diff --git a/gen/cl_options.cpp b/driver/cl_options.cpp similarity index 96% rename from gen/cl_options.cpp rename to driver/cl_options.cpp index a869620f..4374aa33 100644 --- a/gen/cl_options.cpp +++ b/driver/cl_options.cpp @@ -1,4 +1,4 @@ -#include "gen/cl_options.h" +#include "driver/cl_options.h" #include "gen/cl_helpers.h" #include "llvm/Target/TargetMachine.h" @@ -132,8 +132,9 @@ cl::opt output_o("output-o", cl::desc("Write native object")); // Disabling Red Zone -cl::opt disableRedZone("disable-red-zone", +cl::opt disableRedZone("disable-red-zone", cl::desc("Do not emit code that uses the red zone."), + cl::location(global.params.disableRedZone), cl::init(false)); // DDoc options @@ -360,7 +361,7 @@ static cl::opt postconditions("postconditions", cl::init(true)); -static MultiSetter ContractsSetter(false, +static MultiSetter ContractsSetter(false, &global.params.useIn, &global.params.useOut, NULL); static cl::opt contracts("contracts", cl::desc("(*) Enable function pre- and post-conditions"), @@ -374,10 +375,13 @@ static cl::opt > release("release", cl::location(ReleaseSetter), cl::ValueDisallowed); +cl::opt noVerify("noverify", + llvm::cl::desc("Do not run the validation pass before writing bitcode"), + cl::location(global.params.noVerify)); -cl::opt singleObj("singleobj", +cl::opt singleObj("singleobj", cl::desc("Create only a single output object file"), - cl::ZeroOrMore); + cl::location(global.params.singleObj)); cl::opt linkonceTemplates("linkonce-templates", cl::desc("Use linkonce_odr linkage for template symbols instead of weak_odr"), diff --git a/gen/cl_options.h b/driver/cl_options.h similarity index 95% rename from gen/cl_options.h rename to driver/cl_options.h index 53392e36..2fed81b0 100644 --- a/gen/cl_options.h +++ b/driver/cl_options.h @@ -33,7 +33,7 @@ namespace opts { extern cl::opt output_ll; extern cl::opt output_s; extern cl::opt output_o; - extern cl::opt disableRedZone; + extern cl::opt disableRedZone; extern cl::opt ddocDir; extern cl::opt ddocFile; extern cl::opt jsonFile; @@ -50,7 +50,7 @@ namespace opts { extern cl::opt mTargetTriple; extern cl::opt mRelocModel; extern cl::opt mCodeModel; - extern cl::opt singleObj; + extern cl::opt singleObj; extern cl::opt linkonceTemplates; // Arguments to -d-debug diff --git a/gen/linker.cpp b/driver/linker.cpp similarity index 99% rename from gen/linker.cpp rename to driver/linker.cpp index 33bf2c5c..8d189763 100644 --- a/gen/linker.cpp +++ b/driver/linker.cpp @@ -1,4 +1,3 @@ -#include "gen/linker.h" #include "gen/llvm.h" #include "llvm/Linker.h" #include "llvm/Support/FileSystem.h" @@ -13,10 +12,12 @@ #define NO_COUT_LOGGER #include "gen/logger.h" -#include "gen/cl_options.h" #include "gen/optimizer.h" #include "gen/programs.h" +#include "driver/linker.h" +#include "driver/cl_options.h" + ////////////////////////////////////////////////////////////////////////////// // Is this useful? diff --git a/gen/linker.h b/driver/linker.h similarity index 100% rename from gen/linker.h rename to driver/linker.h diff --git a/driver/main.cpp b/driver/main.cpp index 50f8ba03..633f7dc5 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -30,13 +30,13 @@ #include "gen/logger.h" #include "gen/linkage.h" -#include "gen/linker.h" #include "gen/irstate.h" #include "gen/optimizer.h" #include "gen/metadata.h" #include "gen/passes/Passes.h" -#include "gen/cl_options.h" +#include "driver/linker.h" +#include "driver/cl_options.h" #include "gen/cl_helpers.h" using namespace opts; diff --git a/driver/toobj.cpp b/driver/toobj.cpp index 98ce6abc..bdcb8982 100644 --- a/driver/toobj.cpp +++ b/driver/toobj.cpp @@ -24,12 +24,6 @@ #include "gen/optimizer.h" -////////////////////////////////////////////////////////////////////////////////////////// - -extern llvm::cl::opt noVerify; - -////////////////////////////////////////////////////////////////////////////////////////// - // fwd decl void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out, llvm::TargetMachine::CodeGenFileType fileType); @@ -42,7 +36,7 @@ void writeModule(llvm::Module* m, std::string filename) bool reverify = ldc_optimize_module(m); // verify the llvm - if (!noVerify && reverify) { + if (!global.params.noVerify && reverify) { std::string verifyErr; Logger::println("Verifying module... again..."); LOG_SCOPE; diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 62b97266..b5adde87 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -17,8 +17,6 @@ #include "ir/irmodule.h" #include "ir/irtypestruct.h" -#include "gen/cl_options.h" - ////////////////////////////////////////////////////////////////////////////////////////// static LLValue *DtoSlice(DValue *dval) diff --git a/gen/functions.cpp b/gen/functions.cpp index 72c4c342..d7946fa8 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -23,7 +23,6 @@ #include "gen/dvalue.h" #include "gen/abi.h" #include "gen/nested.h" -#include "gen/cl_options.h" #include "gen/pragma.h" using namespace llvm::Attribute; @@ -510,7 +509,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) // parameter attributes if (!fdecl->isIntrinsic()) { set_param_attrs(f, func, fdecl); - if (opts::disableRedZone) { + if (global.params.disableRedZone) { func->addFnAttr(NoRedZone); } } diff --git a/gen/linkage.cpp b/gen/linkage.cpp index 62853374..ba77f90f 100644 --- a/gen/linkage.cpp +++ b/gen/linkage.cpp @@ -1,4 +1,3 @@ #include "linkage.h" -#include "gen/cl_options.h" LLGlobalValue::LinkageTypes templateLinkage; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 17b7119a..6584e7cd 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -22,7 +22,6 @@ #include "gen/functions.h" #include "gen/typeinf.h" #include "gen/todebug.h" -#include "gen/cl_options.h" #include "gen/nested.h" #include "ir/irmodule.h" @@ -1649,7 +1648,7 @@ bool mustDefineSymbol(Dsymbol* s) TemplateInstance* tinst = DtoIsTemplateInstance(s); if (tinst) { - if (!opts::singleObj) + if (!global.params.singleObj) return true; if (!tinst->emittedInModule) diff --git a/gen/module.cpp b/gen/module.cpp index e17d35ee..fc3ca84b 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -20,7 +20,6 @@ #include "gen/abi.h" #include "gen/arrays.h" #include "gen/classes.h" -#include "gen/cl_options.h" #include "gen/functions.h" #include "gen/llvmhelpers.h" #include "gen/logger.h" @@ -39,13 +38,6 @@ #define NEW_MODULEINFO_LAYOUT 1 #endif -////////////////////////////////////////////////////////////////////////////////////////// - -llvm::cl::opt noVerify("noverify", - llvm::cl::desc("Do not run the validation pass before writing bitcode"), - llvm::cl::ZeroOrMore); - -////////////////////////////////////////////////////////////////////////////////////////// static llvm::Function* build_module_function(const std::string &name, const std::list &funcs, const std::list &gates = std::list()) @@ -276,7 +268,7 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) sir->emitFunctionBodies(); // for singleobj-compilation, fully emit all seen template instances - if (opts::singleObj) + if (global.params.singleObj) { while (!ir.seenTemplateInstances.empty()) { @@ -297,7 +289,7 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) genmoduleinfo(); // verify the llvm - if (!noVerify) { + if (!global.params.noVerify) { std::string verifyErr; Logger::println("Verifying module..."); LOG_SCOPE; From 30b20794c7fd414b19cad6b913112924d5a0ee48 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Mon, 2 Apr 2012 16:43:46 +0100 Subject: [PATCH 4/7] Fix D1 frontend --- dmd/mars.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dmd/mars.h b/dmd/mars.h index bc9263fa..53b61d83 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -306,6 +306,11 @@ struct Param const char* llvmArch; const char *targetTriple; const char *dataLayout; + + // Codegen cl options + bool singleObj; + bool disableRedZone; + bool noVerify; #endif }; From a8398d64e829b31ad0be7d53706fcfb7ceb16a0d Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Tue, 3 Apr 2012 21:18:16 +0100 Subject: [PATCH 5/7] Moved configfile to the driver --- CMakeLists.txt | 7 +++---- {gen => driver}/configfile.cpp | 2 +- {gen => driver}/configfile.h | 0 driver/main.cpp | 3 +-- 4 files changed, 5 insertions(+), 7 deletions(-) rename {gen => driver}/configfile.cpp (99%) rename {gen => driver}/configfile.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a5f6b82..6936adac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,8 +268,6 @@ endif(USE_METADATA) # Set up the main ldc/ldc2 target. # set(LDC_LIB LDCShared) - -# Path where ldc executable will be put add_library(${LDC_LIB} SHARED ${LDC_SOURCE_FILES}) # Build ldc set_target_properties( @@ -280,7 +278,7 @@ set_target_properties( ) # LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems -target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}" ${LIBCONFIG_LDFLAGS} config++) +target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}") if(WIN32) target_link_libraries(${LDC_LIB} imagehlp psapi) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") @@ -291,6 +289,7 @@ if(USE_BOEHM_GC) target_link_libraries(${LDC_LIB} ${PROJECT_SOURCE_DIR}/libgc.a) endif(USE_BOEHM_GC) +# Path where ldc executable will be put add_executable(${LDC_EXE} ${DRV_SRC}) # Name of ldc executable set(LDC_EXE_NAME ${PROGRAM_PREFIX}${LDC_EXE}${PROGRAM_SUFFIX}) @@ -301,7 +300,7 @@ set_target_properties( RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" ) -target_link_libraries(${LDC_EXE} ${LDC_LIB}) +target_link_libraries(${LDC_EXE} ${LDC_LIB} ${LIBCONFIG_LDFLAGS} config++) get_target_property(LDC_LOC ${LDC_EXE} LOCATION) diff --git a/gen/configfile.cpp b/driver/configfile.cpp similarity index 99% rename from gen/configfile.cpp rename to driver/configfile.cpp index 7796d382..5adc2653 100644 --- a/gen/configfile.cpp +++ b/driver/configfile.cpp @@ -8,7 +8,7 @@ #include "libconfig.h++" -#include "gen/configfile.h" +#include "driver/configfile.h" #include "mars.h" diff --git a/gen/configfile.h b/driver/configfile.h similarity index 100% rename from gen/configfile.h rename to driver/configfile.h diff --git a/driver/main.cpp b/driver/main.cpp index 633f7dc5..19c40f6f 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -40,8 +40,7 @@ #include "gen/cl_helpers.h" using namespace opts; -#include "gen/configfile.h" - +#include "driver/configfile.h" #include "driver/toobj.h" #if POSIX From 36d4a57297fccb267eb854ddbfc7370a9e1012a8 Mon Sep 17 00:00:00 2001 From: Eldar Insafutdinov Date: Sat, 7 Apr 2012 14:12:10 +0100 Subject: [PATCH 6/7] Default to building ldc as a static library. Added BUILD_SHARED flag to enable dynamic libraries --- CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6936adac..e4065d0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,13 +267,23 @@ endif(USE_METADATA) # # Set up the main ldc/ldc2 target. # +if(BUILD_SHARED) + set(LDC_LIB_TYPE SHARED) +else(BUILD_SHARED) + set(LDC_LIB_TYPE STATIC) +endif(BUILD_SHARED) + set(LDC_LIB LDCShared) -add_library(${LDC_LIB} SHARED ${LDC_SOURCE_FILES}) +add_library(${LDC_LIB} ${LDC_LIB_TYPE} ${LDC_SOURCE_FILES}) # Build ldc set_target_properties( ${LDC_LIB} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib + ARCHIVE_OUTPUT_NAME ldc + LIBRARY_OUTPUT_NAME ldc + RUNTIME_OUTPUT_NAME ldc COMPILE_FLAGS "${LLVM_CXXFLAGS} ${LIBCONFIG_CXXFLAGS} -Wno-deprecated -Wno-write-strings -fexceptions" ) From f1998a61108a7e112fffdd7775a803a4c6e2a030 Mon Sep 17 00:00:00 2001 From: kai Date: Tue, 10 Apr 2012 21:24:21 +0200 Subject: [PATCH 7/7] Minimize differences between original dmd source and ldc1. Mainly affects formatting but I also found some code differences. --- dmd/aggregate.h | 2 +- dmd/argtypes.c | 188 ++++++++++++++++++++++++++++++++++++++++ dmd/arrayop.c | 72 ++++++++-------- dmd/attrib.c | 14 +-- dmd/attrib.h | 2 +- dmd/cast.c | 14 +-- dmd/class.c | 2 +- dmd/constfold.c | 6 +- dmd/declaration.c | 16 +++- dmd/declaration.h | 8 +- dmd/doc.c | 22 ++--- dmd/dsymbol.c | 14 +-- dmd/enum.c | 1 + dmd/expression.c | 71 ++++++++------- dmd/expression.h | 25 +++--- dmd/func.c | 82 +++++++++--------- dmd/html.c | 45 +++++++++- dmd/html.h | 5 +- dmd/idgen.c | 2 + dmd/imphint.c | 2 + dmd/init.c | 3 +- dmd/inline.c | 1 - dmd/interpret.c | 215 +++++++++++++++++++++++----------------------- dmd/lexer.c | 7 +- dmd/lexer.h | 1 + dmd/module.h | 6 +- dmd/mtype.c | 50 +++++++---- dmd/mtype.h | 30 +++++-- dmd/parse.c | 19 ++-- dmd/scope.c | 2 +- dmd/statement.c | 23 ++--- dmd/statement.h | 5 +- dmd/struct.c | 41 ++++++++- dmd/template.c | 48 +++++------ dmd/template.h | 1 - dmd/utf.c | 2 +- 36 files changed, 695 insertions(+), 352 deletions(-) create mode 100644 dmd/argtypes.c diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 5b19d28b..f0a30ec3 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -257,7 +257,7 @@ struct ClassDeclaration : AggregateDeclaration ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration int com; // !=0 if this is a COM class (meaning // it derives from IUnknown) - int isscope; // !=0 if this is a scope class + int isscope; // !=0 if this is an auto class int isabstract; // !=0 if abstract class #if DMDV1 int isnested; // !=0 if is nested diff --git a/dmd/argtypes.c b/dmd/argtypes.c new file mode 100644 index 00000000..2ed89f3a --- /dev/null +++ b/dmd/argtypes.c @@ -0,0 +1,188 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 2010-2011 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// http://www.dsource.org/projects/dmd/browser/branches/dmd-1.x/src/argtypes.c +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include +#include + +#include "mars.h" +#include "dsymbol.h" +#include "mtype.h" +#include "scope.h" +#include "init.h" +#include "expression.h" +#include "attrib.h" +#include "declaration.h" +#include "template.h" +#include "id.h" +#include "enum.h" +#include "import.h" +#include "aggregate.h" +#include "hdrgen.h" + +/**************************************************** + * This breaks a type down into 'simpler' types that can be passed to a function + * in registers, and returned in registers. + * It's highly platform dependent. + * Returning a tuple of zero length means the type cannot be passed/returned in registers. + */ + + +TypeTuple *Type::toArgTypes() +{ + return NULL; // not valid for a parameter +} + + +TypeTuple *TypeBasic::toArgTypes() +{ Type *t1 = NULL; + Type *t2 = NULL; + switch (ty) + { + case Tvoid: + return NULL; + + case Tbool: + case Tint8: + case Tuns8: + case Tint16: + case Tuns16: + case Tint32: + case Tuns32: + case Tfloat32: + case Tint64: + case Tuns64: + case Tfloat64: + case Tfloat80: + t1 = this; + break; + + case Timaginary32: + t1 = Type::tfloat32; + break; + + case Timaginary64: + t1 = Type::tfloat64; + break; + + case Timaginary80: + t1 = Type::tfloat80; + break; + + case Tcomplex32: + if (global.params.is64bit) + t1 = Type::tfloat64; // weird, eh? + else + { + t1 = Type::tfloat64; + t2 = Type::tfloat64; + } + break; + + case Tcomplex64: + //t1 = Type::tfloat64; + //t2 = Type::tfloat64; + break; + + case Tcomplex80: + t1 = Type::tfloat80; + t2 = Type::tfloat80; + break; + + case Tascii: + t1 = Type::tuns8; + break; + + case Twchar: + t1 = Type::tuns16; + break; + + case Tdchar: + t1 = Type::tuns32; + break; + + default: assert(0); + } + + TypeTuple *t; + if (t1) + { + if (t2) + t = new TypeTuple(t1, t2); + else + t = new TypeTuple(t1); + } + else + t = new TypeTuple(); + return t; +} + +TypeTuple *TypeSArray::toArgTypes() +{ +#if DMDV2 + return new TypeTuple(); // pass on the stack for efficiency +#else + return new TypeTuple(Type::tvoidptr); +#endif +} + +TypeTuple *TypeDArray::toArgTypes() +{ + return new TypeTuple(); // pass on the stack for efficiency +} + +TypeTuple *TypeAArray::toArgTypes() +{ + return new TypeTuple(Type::tvoidptr); +} + +TypeTuple *TypePointer::toArgTypes() +{ + return new TypeTuple(this); +} + +TypeTuple *TypeDelegate::toArgTypes() +{ + return new TypeTuple(); // pass on the stack for efficiency +} + +TypeTuple *TypeStruct::toArgTypes() +{ + d_uns64 sz = size(0); + assert(sz < 0xFFFFFFFF); + switch ((unsigned)sz) + { + case 1: + return new TypeTuple(Type::tint8); + case 2: + return new TypeTuple(Type::tint16); + case 4: + return new TypeTuple(Type::tint32); + case 8: + return new TypeTuple(Type::tint64); + } + return new TypeTuple(); // pass on the stack +} + +TypeTuple *TypeEnum::toArgTypes() +{ + return toBasetype()->toArgTypes(); +} + +TypeTuple *TypeTypedef::toArgTypes() +{ + return sym->basetype->toArgTypes(); +} + +TypeTuple *TypeClass::toArgTypes() +{ + return new TypeTuple(Type::tvoidptr); +} + diff --git a/dmd/arrayop.c b/dmd/arrayop.c index 8b847f0a..d3f1c681 100644 --- a/dmd/arrayop.c +++ b/dmd/arrayop.c @@ -314,57 +314,57 @@ Expression *BinExp::arrayOp(Scope *sc) } #endif #endif - /* Not in library, so generate it. - * Construct the function body: - * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++) - * loopbody; - * return p; - */ + /* Not in library, so generate it. + * Construct the function body: + * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++) + * loopbody; + * return p; + */ - Parameters *fparams = new Parameters(); - Expression *loopbody = buildArrayLoop(fparams); + Parameters *fparams = new Parameters(); + Expression *loopbody = buildArrayLoop(fparams); Parameter *p = (*fparams)[0 /*fparams->dim - 1*/]; #if DMDV1 - // for (size_t i = 0; i < p.length; i++) - Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t)); - Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init); - Statement *s1 = new ForStatement(0, + // for (size_t i = 0; i < p.length; i++) + Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t)); + Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init); + Statement *s1 = new ForStatement(0, new ExpStatement(0, d), - new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))), - new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)), - new ExpStatement(0, loopbody)); + new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))), + new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)), + new ExpStatement(0, loopbody)); #else - // foreach (i; 0 .. p.length) - Statement *s1 = new ForeachRangeStatement(0, TOKforeach, - new Parameter(0, NULL, Id::p, NULL), - new IntegerExp(0, 0, Type::tint32), - new ArrayLengthExp(0, new IdentifierExp(0, p->ident)), - new ExpStatement(0, loopbody)); + // foreach (i; 0 .. p.length) + Statement *s1 = new ForeachRangeStatement(0, TOKforeach, + new Parameter(0, NULL, Id::p, NULL), + new IntegerExp(0, 0, Type::tint32), + new ArrayLengthExp(0, new IdentifierExp(0, p->ident)), + new ExpStatement(0, loopbody)); #endif - Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident)); - //printf("s2: %s\n", s2->toChars()); - Statement *fbody = new CompoundStatement(0, s1, s2); + Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident)); + //printf("s2: %s\n", s2->toChars()); + Statement *fbody = new CompoundStatement(0, s1, s2); - /* Construct the function - */ - TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc); - //printf("ftype: %s\n", ftype->toChars()); + /* Construct the function + */ + TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc); + //printf("ftype: %s\n", ftype->toChars()); fd = new FuncDeclaration(loc, 0, ident, STCundefined, ftype); - fd->fbody = fbody; - fd->protection = PROTpublic; + fd->fbody = fbody; + fd->protection = PROTpublic; fd->linkage = LINKc; fd->isArrayOp = 1; - sc->module->importedFrom->members->push(fd); + sc->module->importedFrom->members->push(fd); - sc = sc->push(); - sc->parent = sc->module->importedFrom; - sc->stc = 0; + sc = sc->push(); + sc->parent = sc->module->importedFrom; + sc->stc = 0; sc->linkage = LINKc; - fd->semantic(sc); + fd->semantic(sc); fd->semantic2(sc); fd->semantic3(sc); - sc->pop(); + sc->pop(); #if IN_DMD } else diff --git a/dmd/attrib.c b/dmd/attrib.c index b26aa026..dc194bfb 100644 --- a/dmd/attrib.c +++ b/dmd/attrib.c @@ -585,8 +585,8 @@ void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) case LINKwindows: p = "Windows"; break; case LINKpascal: p = "Pascal"; break; - // LDC - case LINKintrinsic: p = "Intrinsic"; break; + // LDC + case LINKintrinsic: p = "Intrinsic"; break; default: assert(0); @@ -714,12 +714,15 @@ void AlignDeclaration::setScope(Scope *sc) void AlignDeclaration::semantic(Scope *sc) { -// LDC -// we only support packed structs, as from the spec: align(1) struct Packed { ... } -// other alignments are simply ignored. my tests show this is what llvm-gcc does too ... + // LDC + // we only support packed structs, as from the spec: align(1) struct Packed { ... } + // other alignments are simply ignored. my tests show this is what llvm-gcc does too ... + if (decl) { semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign); } + else + assert(0 && "what kind of align use triggers this?"); } @@ -1130,6 +1133,7 @@ void PragmaDeclaration::semantic(Scope *sc) } printf("\n"); } + goto Lnodecl; } else error("unrecognized pragma(%s)", ident->toChars()); diff --git a/dmd/attrib.h b/dmd/attrib.h index b8269525..02db2a3b 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -57,7 +57,7 @@ struct AttribDeclaration : Dsymbol AttribDeclaration *isAttribDeclaration() { return this; } #if IN_DMD - virtual void toObjFile(int multiobj); // compile to .obj file + void toObjFile(int multiobj); // compile to .obj file int cvMember(unsigned char *p); #endif diff --git a/dmd/cast.c b/dmd/cast.c index 04fdb80d..f5e4989f 100644 --- a/dmd/cast.c +++ b/dmd/cast.c @@ -404,12 +404,11 @@ MATCH StringExp::implicitConvTo(Type *t) printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", toChars(), committed, type->toChars(), t->toChars()); #endif - if (!committed) - { if (!committed && t->ty == Tpointer && t->next->ty == Tvoid) { return MATCHnomatch; } + if (!committed) if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer) { if (type->next->ty == Tchar) @@ -428,15 +427,16 @@ MATCH StringExp::implicitConvTo(Type *t) L1: if (t->next->ty == Tchar) return MATCHexact; - else if (t->next->ty == Twchar) - return MATCHexact; - else if (t->next->ty == Tdchar) - return MATCHexact; + else if (!committed) + { if (t->next->ty == Twchar) + return MATCHexact; + else if (t->next->ty == Tdchar) + return MATCHexact; + } break; } } } - } return Expression::implicitConvTo(t); #if 0 m = (MATCH)type->implicitConvTo(t); diff --git a/dmd/class.c b/dmd/class.c index c590f8b2..bf793906 100644 --- a/dmd/class.c +++ b/dmd/class.c @@ -824,7 +824,7 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) { cd->semantic(NULL); if (!cd->baseClass) - cd->error("base class is forward referenced by %s", toChars()); + cd->error("base class is forward referenced by %s", toChars()); } if (this == cd->baseClass) diff --git a/dmd/constfold.c b/dmd/constfold.c index bb70380e..a04fa292 100644 --- a/dmd/constfold.c +++ b/dmd/constfold.c @@ -75,7 +75,7 @@ int ComplexExp::isConst() int NullExp::isConst() { - return 1; + return 0; } int SymOffExp::isConst() @@ -1455,7 +1455,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) if (t->ty == tn->ty) memcpy((unsigned char *)s, &v, sz); else - utf_encode(sz, s, v); + utf_encode(sz, s, v); // Add terminating 0 memset((unsigned char *)s + len * sz, 0, sz); @@ -1579,7 +1579,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) if (homoConcat) memcpy((unsigned char *)s + (sz * es1->len), &v, sz); else - utf_encode(sz, (unsigned char *)s + (sz * es1->len), v); + utf_encode(sz, (unsigned char *)s + (sz * es1->len), v); // Add terminating 0 memset((unsigned char *)s + len * sz, 0, sz); diff --git a/dmd/declaration.c b/dmd/declaration.c index 6471e078..4de203d8 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -591,7 +591,7 @@ void AliasDeclaration::semantic(Scope *sc) } if (!type || type->ty != Terror) { //printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars()); - aliassym = s; + aliassym = s; } this->inSemantic = 0; } @@ -671,7 +671,11 @@ void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (haliassym) { +#if !IN_LLVM + haliassym->toCBuffer(buf, hgs); +#else buf->writestring(haliassym->toChars()); +#endif buf->writeByte(' '); buf->writestring(ident->toChars()); } @@ -683,7 +687,11 @@ void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (aliassym) { +#if !IN_LLVM + aliassym->toCBuffer(buf, hgs); +#else buf->writestring(aliassym->toChars()); +#endif buf->writeByte(' '); buf->writestring(ident->toChars()); } @@ -1427,7 +1435,7 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) fdv->nestedFrameRef = 1; #if IN_LLVM #if DMDV1 - fdv->nestedVars.insert(this); + fdv->nestedVars.insert(this); #endif #endif //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); @@ -1496,7 +1504,7 @@ int VarDeclaration::isSameAsInitializer() } /****************************************** - * If a variable has an scope destructor call, return call for it. + * If a variable has a scope destructor call, return call for it. * Otherwise, return NULL. */ @@ -1504,7 +1512,7 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc) { Expression *e = NULL; //printf("VarDeclaration::callScopeDtor() %s\n", toChars()); - if (storage_class & STCscope && !noscope) + if (storage_class & (STCauto | STCscope) && !noscope) { for (ClassDeclaration *cd = type->isClassHandle(); cd; diff --git a/dmd/declaration.h b/dmd/declaration.h index 7e32a6fc..40239743 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -91,6 +91,8 @@ enum STC #define STCtrusted 0x400000000LL #define STCsystem 0x800000000LL #define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static +#define STCdisable 0x2000000000LL // for functions that are not callable +#define STCresult 0x4000000000LL // for result variables passed to out contracts struct Match { @@ -270,7 +272,7 @@ struct VarDeclaration : Declaration { Initializer *init; unsigned offset; - int noscope; // no scope semantics + int noscope; // no auto semantics #if DMDV2 FuncDeclarations nestedrefs; // referenced by these lexically nested functions bool isargptr; // if parameter that _argptr points to @@ -329,8 +331,8 @@ struct VarDeclaration : Declaration virtual int isSameAsInitializer(); #if IN_DMD - void toObjFile(int multiobj); // compile to .obj file Symbol *toSymbol(); + void toObjFile(int multiobj); // compile to .obj file int cvMember(unsigned char *p); #endif @@ -423,8 +425,8 @@ struct TypeInfoDeclaration : VarDeclaration void toJsonBuffer(OutBuffer *buf); #if IN_DMD - void toObjFile(int multiobj); // compile to .obj file Symbol *toSymbol(); + void toObjFile(int multiobj); // compile to .obj file virtual void toDt(dt_t **pdt); #endif diff --git a/dmd/doc.c b/dmd/doc.c index 1bcb93a9..2d7a48a5 100644 --- a/dmd/doc.c +++ b/dmd/doc.c @@ -254,11 +254,11 @@ void Module::gendocfile() // Set time macros { time_t t; - time(&t); - char *p = ctime(&t); - p = mem.strdup(p); - Macro::define(¯otable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p)); - Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); + time(&t); + char *p = ctime(&t); + p = mem.strdup(p); + Macro::define(¯otable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p)); + Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); } char *docfilename = docfile->toChars(); @@ -1931,11 +1931,11 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) buf->remove(iLineStart, i - iLineStart + eollen); i = iLineStart; - if (inCode && (i <= iCodeStart)) - { // Empty code section, just remove it completely. - inCode = 0; - break; - } + if (inCode && (i <= iCodeStart)) + { // Empty code section, just remove it completely. + inCode = 0; + break; + } if (inCode) { @@ -2010,7 +2010,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) break; } } - if (inCode) + if (inCode) s->error("unmatched --- in DDoc comment"); ; } diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index 08f26ce3..1318299e 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -221,10 +221,10 @@ char *Dsymbol::locToChars() if (!loc.filename) // avoid bug 5861. { - Module *m = getModule(); + Module *m = getModule(); - if (m && m->srcfile) - loc.filename = m->srcfile->toChars(); + if (m && m->srcfile) + loc.filename = m->srcfile->toChars(); } return loc.toChars(); } @@ -556,10 +556,10 @@ void Dsymbol::error(const char *format, ...) if (m && m->srcfile) loc.filename = m->srcfile->toChars(); } - va_list ap; - va_start(ap, format); + va_list ap; + va_start(ap, format); verror(loc, format, ap); - va_end(ap); + va_end(ap); } void Dsymbol::error(Loc loc, const char *format, ...) @@ -1023,7 +1023,7 @@ static int getNthSymbolDg(void *ctx, size_t n, Dsymbol *sym) if (n == p->nth) { p->sym = sym; return 1; - } + } return 0; } diff --git a/dmd/enum.c b/dmd/enum.c index 7d4cdddc..7c0c40bd 100644 --- a/dmd/enum.c +++ b/dmd/enum.c @@ -32,6 +32,7 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype) sinit = NULL; #endif isdeprecated = 0; + isdone = 0; } Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s) diff --git a/dmd/expression.c b/dmd/expression.c index 283fe485..74eede68 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -16,6 +16,7 @@ #if _MSC_VER #include #else +#include #endif #if _WIN32 && __DMC__ @@ -125,8 +126,8 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, //printf("rewriting e1 to %s's this\n", f->toChars()); n++; - // LDC seems dmd misses it sometimes here :/ - f->vthis->nestedref = 1; + // LDC seems dmd misses it sometimes here :/ + f->vthis->nestedref = 1; e1 = new VarExp(loc, f->vthis); } @@ -780,7 +781,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum { // If not D linkage, do promotions - // LDC: don't do promotions on intrinsics + // LDC: don't do promotions on intrinsics if (tf->linkage != LINKd && tf->linkage != LINKintrinsic) { // Promote bytes, words, etc., to ints @@ -1357,7 +1358,8 @@ Expressions *Expression::arraySyntaxCopy(Expressions *exps) for (size_t i = 0; i < a->dim; i++) { Expression *e = (Expression *)exps->data[i]; - e = e->syntaxCopy(); + if (e) + e = e->syntaxCopy(); a->data[i] = e; } } @@ -3189,7 +3191,7 @@ void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) { size_t dim = elements ? elements->dim : 0; - buf->printf("A%zu", dim); + buf->printf("A%u", dim); for (size_t i = 0; i < dim; i++) { Expression *e = elements->tdata()[i]; e->toMangleBuffer(buf); @@ -3291,7 +3293,7 @@ void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) { size_t dim = keys->dim; - buf->printf("A%zu", dim); + buf->printf("A%u", dim); for (size_t i = 0; i < dim; i++) { Expression *key = (Expression *)keys->data[i]; Expression *value = (Expression *)values->data[i]; @@ -3396,23 +3398,23 @@ Expression *StructLiteralExp::semantic(Scope *sc) { if (v->init->isVoidInitializer()) e = NULL; else - { e = v->init->toExpression(); - if (!e) - { error("cannot make expression out of initializer for %s", v->toChars()); + { e = v->init->toExpression(); + if (!e) + { error("cannot make expression out of initializer for %s", v->toChars()); return new ErrorExp(); - } - else if (v->scope) + } + else if (v->scope) { // Do deferred semantic analysis - Initializer *i2 = v->init->syntaxCopy(); + Initializer *i2 = v->init->syntaxCopy(); i2 = i2->semantic(v->scope, v->type, WANTinterpret); - e = i2->toExpression(); + e = i2->toExpression(); // remove v->scope (see bug 3426) // but not if gagged, for we might be called again. if (!global.gag) - v->scope = NULL; + v->scope = NULL; + } } } - } else e = v->type->defaultInitLiteral(loc); offset = v->offset + v->type->size(); @@ -3545,7 +3547,7 @@ void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void StructLiteralExp::toMangleBuffer(OutBuffer *buf) { size_t dim = elements ? elements->dim : 0; - buf->printf("S%zu", dim); + buf->printf("S%u", dim); for (size_t i = 0; i < dim; i++) { Expression *e = (Expression *)elements->data[i]; if (e) @@ -5047,6 +5049,17 @@ Expression *IsExp::semantic(Scope *sc) goto Lno; break; + case TOKargTypes: + /* Generate a type tuple of the equivalent types used to determine if a + * function argument of this type can be passed in registers. + * The results of this are highly platform dependent, and intended + * primarly for use in implementing va_arg(). + */ + tded = targ->toArgTypes(); + if (!tded) + goto Lno; // not valid for a parameter + break; + default: assert(0); } @@ -5744,7 +5757,7 @@ Expression *DotIdExp::semantic(Scope *sc) else { if (e1->op != TOKtype) - e1 = resolveProperties(sc, e1); + e1 = resolveProperties(sc, e1); eleft = NULL; eright = e1; } @@ -6240,7 +6253,7 @@ L1: } else #endif - ti->semantic(sc); + ti->semantic(sc); if (!ti->inst) // if template failed to expand return new ErrorExp(); Dsymbol *s = ti->inst->toAlias(); @@ -6450,7 +6463,7 @@ Expression *DelegateExp::semantic(Scope *sc) { m = sc->module; e1 = e1->semantic(sc); - // LDC we need a copy as we store the LLVM tpye in TypeFunction, and delegate/members have different types for 'this' + // LDC we need a copy as we store the LLVM tpye in TypeFunction, and delegate/members have different types for 'this' type = new TypeDelegate(func->type->syntaxCopy()); type = type->semantic(loc, sc); AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); @@ -7314,14 +7327,14 @@ Expression *AddrExp::semantic(Scope *sc) { VarExp *dve = (VarExp *)e1; FuncDeclaration *f = dve->var->isFuncDeclaration(); - VarDeclaration *v = dve->var->isVarDeclaration(); + VarDeclaration *v = dve->var->isVarDeclaration(); - // LDC - if (f && f->isIntrinsic()) - { - error("cannot take the address of intrinsic function %s", e1->toChars()); - return this; - } + // LDC + if (f && f->isIntrinsic()) + { + error("cannot take the address of intrinsic function %s", e1->toChars()); + return this; + } if (f && f->isNested()) { @@ -9631,7 +9644,7 @@ Expression *MulExp::semantic(Scope *sc) if (t2->isimaginary()) { Expression *e; - switch (t1->ty) + switch (t1->toBasetype()->ty) { case Timaginary32: type = Type::tfloat32; break; case Timaginary64: type = Type::tfloat64; break; @@ -9705,7 +9718,7 @@ Expression *DivExp::semantic(Scope *sc) { if (t2->isimaginary()) { - switch (t1->ty) + switch (t1->toBasetype()->ty) { case Timaginary32: type = Type::tfloat32; break; case Timaginary64: type = Type::tfloat64; break; @@ -9779,7 +9792,7 @@ Expression *ShlExp::semantic(Scope *sc) #if !IN_LLVM e2 = e2->castTo(sc, Type::tshiftcnt); #else - e2 = e2->castTo(sc, e1->type); + e2 = e2->castTo(sc, e1->type); #endif type = e1->type; } diff --git a/dmd/expression.h b/dmd/expression.h index ffc095ca..b42f3178 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -52,7 +52,6 @@ enum TOK; #if IN_DMD // Back end struct IRState; - struct dt_t; struct elem; struct Symbol; // back end symbol @@ -470,6 +469,9 @@ struct ArrayLiteralExp : Expression int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); int isBool(int result); +#if IN_DMD + elem *toElem(IRState *irs); +#endif int checkSideEffect(int flag); StringExp *toString(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -478,14 +480,14 @@ struct ArrayLiteralExp : Expression Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); +#if IN_DMD + dt_t **toDt(dt_t **pdt); +#endif Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); -#if IN_DMD - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -#elif IN_LLVM +#if IN_LLVM DValue* toElem(IRState* irs); llvm::Constant *toConstElem(IRState *irs); #endif @@ -525,7 +527,7 @@ struct AssocArrayLiteralExp : Expression struct StructLiteralExp : Expression { - StructDeclaration *sd; // which aggregate this is for + StructDeclaration *sd; // which aggregate this is for Expressions *elements; // parallels sd->fields[] with // NULL entries for fields to skip Type *stype; // final type of result (can be different from sd's type) @@ -544,21 +546,24 @@ struct StructLiteralExp : Expression Expression *semantic(Scope *sc); Expression *getField(Type *type, unsigned offset); int getFieldIndex(Type *type, unsigned offset); +#if IN_DMD + elem *toElem(IRState *irs); +#endif int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); Expression *optimize(int result); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); +#if IN_DMD + dt_t **toDt(dt_t **pdt); +#endif Expression *toLvalue(Scope *sc, Expression *e); int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); -#if IN_DMD - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -#elif IN_LLVM +#if IN_LLVM DValue* toElem(IRState* irs); llvm::Constant *toConstElem(IRState *irs); llvm::StructType *constType; diff --git a/dmd/func.c b/dmd/func.c index 999b39d9..982bb573 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -55,6 +55,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla #if IN_GCC v_argptr = NULL; #endif + v_argsave = NULL; parameters = NULL; labtab = NULL; overnext = NULL; @@ -216,7 +217,7 @@ void FuncDeclaration::semantic(Scope *sc) error("_ctor is reserved for constructors"); if (isConst() || isAuto() || isScope()) - error("functions cannot be const, auto or scope"); + error("functions cannot be const or auto"); if (isAbstract() && !isVirtual()) error("non-virtual functions cannot be abstract"); @@ -1240,11 +1241,11 @@ void FuncDeclaration::semantic3(Scope *sc) error("no match for implicit super() call in constructor"); else { - Statement *s = new ExpStatement(0, e); - fbody = new CompoundStatement(0, s, fbody); + Statement *s = new ExpStatement(0, e); + fbody = new CompoundStatement(0, s, fbody); + } } } - } else if (fes) { // For foreach(){} body, append a return 0; Expression *e = new IntegerExp(0); @@ -1342,46 +1343,47 @@ void FuncDeclaration::semantic3(Scope *sc) } else { // Initialize _argptr to point past non-variadic arg - VarDeclaration *p; - unsigned offset = 0; + VarDeclaration *p; + unsigned offset = 0; - Expression *e1 = new VarExp(0, argptr); - // Find the last non-ref parameter - if (parameters && parameters->dim) - { - int lastNonref = parameters->dim -1; - p = (VarDeclaration *)parameters->data[lastNonref]; - /* The trouble with out and ref parameters is that taking - * the address of it doesn't work, because later processing - * adds in an extra level of indirection. So we skip over them. - */ - while (p->storage_class & (STCout | STCref)) + Expression *e1 = new VarExp(0, argptr); + // Find the last non-ref parameter + if (parameters && parameters->dim) { - --lastNonref; - offset += PTRSIZE; - if (lastNonref < 0) - { - p = v_arguments; - break; - } + int lastNonref = parameters->dim -1; p = (VarDeclaration *)parameters->data[lastNonref]; + /* The trouble with out and ref parameters is that taking + * the address of it doesn't work, because later processing + * adds in an extra level of indirection. So we skip over them. + */ + while (p->storage_class & (STCout | STCref)) + { + --lastNonref; + offset += PTRSIZE; + if (lastNonref < 0) + { + p = v_arguments; + break; + } + p = (VarDeclaration *)parameters->data[lastNonref]; + } } + else + p = v_arguments; // last parameter is _arguments[] + if (p->storage_class & STClazy) + // If the last parameter is lazy, it's the size of a delegate + offset += PTRSIZE * 2; + else + offset += p->type->size(); + offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size + Expression *e = new SymOffExp(0, p, offset); + e->type = Type::tvoidptr; + //e = e->semantic(sc); + e = new AssignExp(0, e1, e); + e->type = t; + a->push(new ExpStatement(0, e)); } - else - p = v_arguments; // last parameter is _arguments[] - if (p->storage_class & STClazy) - // If the last parameter is lazy, it's the size of a delegate - offset += PTRSIZE * 2; - else - offset += p->type->size(); - offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size - Expression *e = new SymOffExp(0, p, offset); - e->type = Type::tvoidptr; - //e = e->semantic(sc); - e = new AssignExp(0, e1, e); - e->type = t; - a->push(new ExpStatement(0, e)); -#endif // IN_GCC +#endif } if (_arguments) @@ -2632,7 +2634,7 @@ int FuncDeclaration::needsClosure() { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j]; assert(f != this); - //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf); + //printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf); if (f->isThis() || f->tookAddressOf) goto Lyes; // assume f escapes this function's scope diff --git a/dmd/html.c b/dmd/html.c index 0e2f0ab7..d26ce48a 100644 --- a/dmd/html.c +++ b/dmd/html.c @@ -1,10 +1,10 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com // License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. +// in artistic.txt, or the GNU General Public License in gpl.txt. // See the included readme.txt for details. @@ -21,8 +21,46 @@ #include "mars.h" #include "html.h" +#if MARS || IN_LLVM #include #include "root.h" +//#include "../mars/mars.h" +#else +#include "outbuf.h" +#include "msgs2.h" + +extern void html_err(const char *, unsigned, unsigned, ...); + +static char __file__[] = __FILE__; /* for tassert.h */ +#include "tassert.h" +#endif + +#if __GNUC__ +int memicmp(const char *s1, const char *s2, int n); +#if 0 +{ + int result = 0; + + for (int i = 0; i < n; i++) + { char c1 = s1[i]; + char c2 = s2[i]; + + result = c1 - c2; + if (result) + { + if ('A' <= c1 && c1 <= 'Z') + c1 += 'a' - 'A'; + if ('A' <= c2 && c2 <= 'Z') + c2 += 'a' - 'A'; + result = c1 - c2; + if (result) + break; + } + } + return result; +} +#endif +#endif extern int HtmlNamedEntity(unsigned char *p, int length); @@ -530,7 +568,7 @@ void Html::scanCDATA() * right. */ linnum++; - dbuf->writeUTF8('\n'); + dbuf->writeByte('\n'); p += lineSepLength; continue; } @@ -550,6 +588,7 @@ void Html::scanCDATA() } } + /******************************************** * Convert an HTML character entity into a character. * Forms are: diff --git a/dmd/html.h b/dmd/html.h index f1956847..98a5285b 100644 --- a/dmd/html.h +++ b/dmd/html.h @@ -1,11 +1,10 @@ -// Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com // License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. +// in artistic.txt, or the GNU General Public License in gpl.txt. // See the included readme.txt for details. #ifndef DMD_HTML_H diff --git a/dmd/idgen.c b/dmd/idgen.c index 3d048ab5..7841dc59 100644 --- a/dmd/idgen.c +++ b/dmd/idgen.c @@ -4,6 +4,7 @@ // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com +// http://www.dsource.org/projects/dmd/browser/branches/dmd-1.x/src/idgen.c // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. @@ -92,6 +93,7 @@ Msgtable msgtable[] = { "_arguments" }, { "_argptr" }, { "_match" }, + { "m_align" }, { "LINE", "__LINE__" }, { "FILE", "__FILE__" }, diff --git a/dmd/imphint.c b/dmd/imphint.c index 96b1b88a..df86e01c 100644 --- a/dmd/imphint.c +++ b/dmd/imphint.c @@ -15,6 +15,8 @@ #include #include +#include "mars.h" + /****************************************** * Looks for undefined identifier s to see * if it might be undefined because an import diff --git a/dmd/init.c b/dmd/init.c index 9c269790..760424a9 100644 --- a/dmd/init.c +++ b/dmd/init.c @@ -484,7 +484,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) } if ((unsigned long) dim * t->nextOf()->size() >= amax) - { error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->nextOf()->size()); + { error(loc, "array dimension %u exceeds max of %u", dim, amax / t->nextOf()->size()); goto Lerr; } return this; @@ -540,6 +540,7 @@ Expression *ArrayInitializer::toExpression() elements = new Expressions(); elements->setDim(edim); + elements->zero(); for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index[i]) diff --git a/dmd/inline.c b/dmd/inline.c index 3fe2f825..82013857 100644 --- a/dmd/inline.c +++ b/dmd/inline.c @@ -1802,4 +1802,3 @@ Expression *Expression::inlineCopy(Scope *sc) return e; #endif } - diff --git a/dmd/interpret.c b/dmd/interpret.c index e1000c98..05ce3359 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -1,4 +1,3 @@ - // Compiler implementation of the D programming language // Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved @@ -983,14 +982,14 @@ void scrubArray(Loc loc, Expressions *elems); Expression *scrubReturnValue(Loc loc, Expression *e) { if (e->op == TOKclassreference) - { + { error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars()); return EXP_CANT_INTERPRET; - } + } if (e->op == TOKslice) - { + { e = resolveSlice(e); - } + } if (e->op == TOKstructliteral) { StructLiteralExp *se = (StructLiteralExp *)e; @@ -1038,7 +1037,7 @@ Expression *ReturnStatement::interpret(InterState *istate) START() if (!exp) return EXP_VOID_INTERPRET; - assert(istate && istate->fd && istate->fd->type); + assert(istate && istate->fd && istate->fd->type); #if DMDV2 /* If the function returns a ref AND it's been called from an assignment, * we need to return an lvalue. Otherwise, just do an (rvalue) interpret. @@ -1162,7 +1161,7 @@ Expression *DoStatement::interpret(InterState *istate) if (e == EXP_CONTINUE_INTERPRET) if (!istate->gotoTarget || istate->gotoTarget == this) { - goto Lcontinue; + goto Lcontinue; } else // else continue at a higher level return e; @@ -1240,7 +1239,7 @@ Expression *ForStatement::interpret(InterState *istate) if (!istate->gotoTarget || istate->gotoTarget == this) { istate->gotoTarget = NULL; - return NULL; + return NULL; } // else break at a higher level } if (e == EXP_CONTINUE_INTERPRET) @@ -1248,7 +1247,7 @@ Expression *ForStatement::interpret(InterState *istate) if (!istate->gotoTarget || istate->gotoTarget == this) { istate->gotoTarget = NULL; - goto Lcontinue; + goto Lcontinue; } // else continue at a higher level } if (e) @@ -1339,7 +1338,7 @@ Expression *SwitchStatement::interpret(InterState *istate) if (!istate->gotoTarget || istate->gotoTarget == this) { istate->gotoTarget = NULL; - return NULL; + return NULL; } // else break at a higher level } return e; @@ -1730,8 +1729,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) } if (type->ty != Tpointer) { // Probably impossible - error("Cannot interpret %s at compile time", toChars()); - return EXP_CANT_INTERPRET; + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; } Type *pointee = ((TypePointer *)type)->next; Expression *val = getVarExp(loc, istate, var, goal); @@ -1898,8 +1897,8 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal } else { - if (e && !e->type) - e->type = v->type; + if (e && !e->type) + e->type = v->type; if (e) e = e->interpret(istate, ctfeNeedAnyValue); if (e == EXP_CANT_INTERPRET && !global.gag && !CtfeStatus::stackTraceCallsToSuppress) @@ -1920,8 +1919,8 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal { if (v->init->isVoidInitializer()) { - error(loc, "variable %s is used before initialization", v->toChars()); - return EXP_CANT_INTERPRET; + error(loc, "variable %s is used before initialization", v->toChars()); + return EXP_CANT_INTERPRET; } e = v->init->toExpression(); e = e->interpret(istate); @@ -2203,7 +2202,7 @@ Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) #if DMDV2 if (((TypeNext *)type)->next->mod & (MODconst | MODimmutable)) { // If it's immutable, we don't need to dup it - return this; + return this; } #endif return copyLiteral(this); @@ -2320,8 +2319,8 @@ Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) /* We don't know how to deal with overlapping fields */ if (sd->hasUnions) - { error("Unions with overlapping fields are not yet supported in CTFE"); - return EXP_CANT_INTERPRET; + { error("Unions with overlapping fields are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; } if (ownedByCtfe) return copyLiteral(this); @@ -2469,13 +2468,13 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) Expression *se = newtype->defaultInitLiteral(); #if DMDV2 if (member) - { + { int olderrors = global.errors; member->interpret(istate, arguments, se); if (olderrors != global.errors) { error("cannot evaluate %s at compile time", toChars()); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; } } #else // The above code would fail on D1 because it doesn't use STRUCTTHISREF, @@ -2552,7 +2551,7 @@ Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expressi #define UNA_INTERPRET(op) \ Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ -{ \ +{ \ return interpretCommon(istate, goal, &op); \ } @@ -2715,7 +2714,7 @@ Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp) } if (this->e2->type->ty == Tpointer && this->e1->type->isintegral() && op==TOKadd) { - e1 = this->e1->interpret(istate); + e1 = this->e1->interpret(istate); if (exceptionOrCantInterpret(e1)) return e1; e2 = this->e2->interpret(istate, ctfeNeedLvalue); @@ -2751,7 +2750,7 @@ Lcant: #define BIN_INTERPRET(op) \ Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ -{ \ +{ \ return interpretCommon(istate, goal, &op); \ } @@ -2967,28 +2966,28 @@ Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, */ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expression *index, Expression *newval) { - /* Create new associative array literal reflecting updated key/value - */ - Expressions *keysx = aae->keys; + /* Create new associative array literal reflecting updated key/value + */ + Expressions *keysx = aae->keys; Expressions *valuesx = aae->values; - int updated = 0; - for (size_t j = valuesx->dim; j; ) - { j--; + int updated = 0; + for (size_t j = valuesx->dim; j; ) + { j--; Expression *ekey = aae->keys->tdata()[j]; Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); if (exceptionOrCantInterpret(ex)) return ex; - if (ex->isBool(TRUE)) + if (ex->isBool(TRUE)) { valuesx->tdata()[j] = newval; - updated = 1; - } - } - if (!updated) - { // Append index/newval to keysx[]/valuesx[] - valuesx->push(newval); - keysx->push(index); - } - return newval; + updated = 1; + } + } + if (!updated) + { // Append index/newval to keysx[]/valuesx[] + valuesx->push(newval); + keysx->push(index); + } + return newval; } // Return true if e is derived from UnaryExp. @@ -3009,7 +3008,7 @@ UnaExp *isUnaExp(Expression *e) default: break; } - return NULL; + return NULL; } // Returns the variable which is eventually modified, or NULL if an rvalue. @@ -3071,7 +3070,7 @@ bool needToCopyLiteral(Expression *expr) continue; default: return false; - } + } } } @@ -3234,7 +3233,7 @@ Expression *paintTypeOntoLiteral(Type *type, Expression *lit) { IndexExp *ie = (IndexExp *)lit; e = new IndexExp(lit->loc, ie->e1, ie->e2); - } + } else if (lit->op == TOKarrayliteral) { e = new SliceExp(lit->loc, lit, @@ -3717,8 +3716,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ { error("nested structs with constructors are not yet supported in CTFE (Bug 6419)"); return EXP_CANT_INTERPRET; + } } - } newval = ctfeCast(loc, type, type, newval); if (exceptionOrCantInterpret(newval)) return newval; @@ -3752,7 +3751,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // (We already have 'newval' for arraylength operations) // --------------------------------------- if (wantRef && !fp && this->e1->op != TOKarraylength) - { + { newval = this->e2->interpret(istate, ctfeNeedLvalue); if (exceptionOrCantInterpret(newval)) return newval; @@ -3763,7 +3762,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ newval->type->ty == Tclass)) { newval = newval->interpret(istate); - } + } if (newval->op == TOKassocarrayliteral || newval->op == TOKstring || newval->op==TOKarrayliteral) @@ -3785,7 +3784,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ * create nested AA literals, and change it into a assignment. */ if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) - { + { IndexExp *ie = (IndexExp *)e1; int depth = 0; // how many nested AA indices are there? while (ie->e1->op == TOKindex && ((IndexExp *)ie->e1)->e1->type->toBasetype()->ty == Taarray) @@ -4171,7 +4170,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // aggregate[] = newval // aggregate[low..upp] = newval // ------------------------------ - SliceExp * sexp = (SliceExp *)e1; + SliceExp * sexp = (SliceExp *)e1; // Set the $ variable Expression *oldval = sexp->e1; bool assignmentToSlicedPointer = false; @@ -4198,18 +4197,18 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ sexp->lengthVar->setValue(arraylen); } - Expression *upper = NULL; - Expression *lower = NULL; - if (sexp->upr) - upper = sexp->upr->interpret(istate); + Expression *upper = NULL; + Expression *lower = NULL; + if (sexp->upr) + upper = sexp->upr->interpret(istate); if (exceptionOrCantInterpret(upper)) { if (sexp->lengthVar) ctfeStack.pop(sexp->lengthVar); // $ is defined only in [L..U] return upper; - } - if (sexp->lwr) - lower = sexp->lwr->interpret(istate); + } + if (sexp->lwr) + lower = sexp->lwr->interpret(istate); if (sexp->lengthVar) ctfeStack.pop(sexp->lengthVar); // $ is defined only in [L..U] if (exceptionOrCantInterpret(lower)) @@ -4223,8 +4222,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ { error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); - return EXP_CANT_INTERPRET; - } + return EXP_CANT_INTERPRET; + } if (upperbound == lowerbound) return newval; @@ -4241,7 +4240,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (aggregate->op == TOKindex || aggregate->op == TOKdotvar || aggregate->op == TOKslice || aggregate->op == TOKstar || aggregate->op == TOKcall) - { + { aggregate = aggregate->interpret(istate, ctfeNeedLvalue); if (exceptionOrCantInterpret(aggregate)) return aggregate; @@ -4262,7 +4261,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ } } if (aggregate->op == TOKvar) - { + { VarExp *ve = (VarExp *)(aggregate); VarDeclaration *v = ve->var->isVarDeclaration(); aggregate = v->getValue(); @@ -4305,7 +4304,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ } if (!wantRef && newval->op == TOKslice) - { + { newval = resolveSlice(newval); if (newval == EXP_CANT_INTERPRET) { @@ -4320,16 +4319,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ } // For slice assignment, we check that the lengths match. - size_t srclen = 0; - if (newval->op == TOKarrayliteral) - srclen = ((ArrayLiteralExp *)newval)->elements->dim; - else if (newval->op == TOKstring) - srclen = ((StringExp *)newval)->len; + size_t srclen = 0; + if (newval->op == TOKarrayliteral) + srclen = ((ArrayLiteralExp *)newval)->elements->dim; + else if (newval->op == TOKstring) + srclen = ((StringExp *)newval)->len; if (!isBlockAssignment && srclen != (upperbound - lowerbound)) - { - error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); + { + error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); return EXP_CANT_INTERPRET; - } + } if (!isBlockAssignment && newval->op == TOKarrayliteral && existingAE) { @@ -4353,14 +4352,14 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ */ sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, firstIndex); return newval; - } + } else if (newval->op == TOKarrayliteral && existingSE) { /* Mixed slice: it was initialized as a string literal. * Now a slice of it is being set with an array literal. */ sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, firstIndex); return newval; - } + } else if (existingSE) { // String literal block slice assign unsigned value = newval->toInteger(); @@ -4375,8 +4374,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ default: assert(0); break; + } } - } if (goal == ctfeNeedNothing) return NULL; // avoid creating an unused literal SliceExp *retslice = new SliceExp(loc, existingSE, @@ -4384,14 +4383,14 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t)); retslice->type = this->type; return retslice->interpret(istate); - } + } else if (existingAE) - { + { /* Block assignment, initialization of static arrays * x[] = e * x may be a multidimensional static array. (Note that this * only happens with array literals, never with strings). - */ + */ Expressions * w = existingAE->elements; assert( existingAE->type->ty == Tsarray || existingAE->type->ty == Tarray); @@ -4410,13 +4409,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // Multidimensional array block assign recursiveBlockAssign((ArrayLiteralExp *)w->tdata()[j+firstIndex], newval, wantRef); else - { + { if (wantRef || cow) existingAE->elements->tdata()[j+firstIndex] = newval; else assignInPlace(existingAE->elements->tdata()[j+firstIndex], newval); + } } - } if (goal == ctfeNeedNothing) return NULL; // avoid creating an unused literal SliceExp *retslice = new SliceExp(loc, existingAE, @@ -4518,14 +4517,14 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) { error("%s does not evaluate to a boolean", e->toChars()); e = EXP_CANT_INTERPRET; + } } } - } else { error("%s cannot be interpreted as a boolean", e->toChars()); e = EXP_CANT_INTERPRET; - } + } } if (e != EXP_CANT_INTERPRET && goal != ctfeNeedNothing) e = new IntegerExp(loc, result, type); @@ -4567,14 +4566,14 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal) { error("%s cannot be interpreted as a boolean", e->toChars()); e = EXP_CANT_INTERPRET; + } } } - } else { error("%s cannot be interpreted as a boolean", e->toChars()); e = EXP_CANT_INTERPRET; - } + } } if (e != EXP_CANT_INTERPRET && goal != ctfeNeedNothing) e = new IntegerExp(loc, result, type); @@ -4853,9 +4852,9 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) } if (!v->getValue()) { Expression *newval = v->init->toExpression(); - // Bug 4027. Copy constructors are a weird case where the - // initializer is a void function (the variable is modified - // through a reference parameter instead). + // Bug 4027. Copy constructors are a weird case where the + // initializer is a void function (the variable is modified + // through a reference parameter instead). newval = newval->interpret(istate); if (exceptionOrCantInterpret(newval)) { @@ -4863,11 +4862,11 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) ctfeStack.endFrame(0); return newval; } - if (newval != EXP_VOID_INTERPRET) + if (newval != EXP_VOID_INTERPRET) { // v isn't necessarily null. v->setValueWithoutChecking(copyLiteral(newval)); - } + } } if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) e = e2; @@ -4906,13 +4905,13 @@ Expression *CondExp::interpret(InterState *istate, CtfeGoal goal) return e; if (isTrueBool(e)) e = e1->interpret(istate, goal); - else if (e->isBool(FALSE)) + else if (e->isBool(FALSE)) e = e2->interpret(istate, goal); - else + else { error("%s does not evaluate to boolean result at compile time", econd->toChars()); - e = EXP_CANT_INTERPRET; + e = EXP_CANT_INTERPRET; } return e; } @@ -5007,7 +5006,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) if (this->e1->type->toBasetype()->ty == Tpointer) { // Indexing a pointer. Note that there is no $ in this case. - e1 = this->e1->interpret(istate); + e1 = this->e1->interpret(istate); if (exceptionOrCantInterpret(e1)) return e1; e2 = this->e2->interpret(istate); @@ -5047,7 +5046,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) } /* Set the $ variable. * Note that foreach uses indexing but doesn't need $ - */ + */ if (lengthVar && (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKslice)) { @@ -5131,7 +5130,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) if (this->e1->type->toBasetype()->ty == Tpointer) { // Slicing a pointer. Note that there is no $ in this case. - e1 = this->e1->interpret(istate); + e1 = this->e1->interpret(istate); if (exceptionOrCantInterpret(e1)) return e1; if (e1->op == TOKint64) @@ -5258,7 +5257,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) new IntegerExp(loc, ilwr, lwr->type), new IntegerExp(loc, iupr, upr->type)); e->type = type; - return e; + return e; } if (e1->op == TOKarrayliteral || e1->op == TOKstring) @@ -5267,7 +5266,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) { error("slice [%jd..%jd] exceeds array bounds [0..%jd]", ilwr, iupr, dollar); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; } } e = new SliceExp(loc, e1, lwr, upr); @@ -5434,7 +5433,7 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) { error("reinterpreting cast from %s* to %s* is not supported in CTFE", elemtype->toChars(), pointee->toChars()); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; } if (ultimateSrc->ty == Tvoid) castBackFromVoid = true; @@ -5606,15 +5605,15 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) ex = ex->interpret(istate); if (exceptionOrCantInterpret(ex)) return ex; - if (ex->op == TOKstructliteral) - { StructLiteralExp *se = (StructLiteralExp *)ex; + if (ex->op == TOKstructliteral) + { StructLiteralExp *se = (StructLiteralExp *)ex; dinteger_t offset = ae->e2->toInteger(); - e = se->getField(type, offset); - if (!e) - e = EXP_CANT_INTERPRET; - return e; - } + e = se->getField(type, offset); + if (!e) + e = EXP_CANT_INTERPRET; + return e; } + } e = Ptr(type, e1); } #if DMDV2 @@ -5742,7 +5741,7 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) #endif if (ex->op == TOKaddress) ex = ((AddrExp *)ex)->e1; - VarDeclaration *v = var->isVarDeclaration(); + VarDeclaration *v = var->isVarDeclaration(); if (!v) error("CTFE internal error: %s", toChars()); if (ex->op == TOKnull && ex->type->toBasetype()->ty == Tclass) @@ -5786,11 +5785,11 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) e->type = type; return e; } - if (!e) - { - error("couldn't find field %s in %s", v->toChars(), type->toChars()); - e = EXP_CANT_INTERPRET; - } + if (!e) + { + error("couldn't find field %s in %s", v->toChars(), type->toChars()); + e = EXP_CANT_INTERPRET; + } // If it is an rvalue literal, return it... if (e->op == TOKstructliteral || e->op == TOKarrayliteral || e->op == TOKassocarrayliteral || e->op == TOKstring) @@ -6253,7 +6252,7 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc, for (size_t i = 0; i < args.dim; i++) { Expression *earg = arguments->tdata()[i]; - earg = earg->interpret(istate); + earg = earg->interpret(istate); if (exceptionOrCantInterpret(earg)) return earg; args.tdata()[i] = earg; diff --git a/dmd/lexer.c b/dmd/lexer.c index c3070f5d..72959b8a 100644 --- a/dmd/lexer.c +++ b/dmd/lexer.c @@ -302,10 +302,10 @@ Lexer::Lexer(Module *mod, void Lexer::error(const char *format, ...) { - va_list ap; - va_start(ap, format); + va_list ap; + va_start(ap, format); verror(loc, format, ap); - va_end(ap); + va_end(ap); } void Lexer::error(Loc loc, const char *format, ...) @@ -3027,6 +3027,7 @@ static Keyword keywords[] = //{ "manifest", TOKmanifest }, // Added after 1.0 + { "__argTypes", TOKargTypes }, { "ref", TOKref }, { "macro", TOKmacro }, #if DMDV2 diff --git a/dmd/lexer.h b/dmd/lexer.h index c844f155..8fb90863 100644 --- a/dmd/lexer.h +++ b/dmd/lexer.h @@ -152,6 +152,7 @@ enum TOK TOKunittest, // Added after 1.0 + TOKargTypes, TOKref, TOKmacro, #if DMDV2 diff --git a/dmd/module.h b/dmd/module.h index 086e0ee8..bea6e17d 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -143,9 +143,9 @@ struct Module : Package void parse(); // syntactic parse #endif void importAll(Scope *sc); - void semantic(); // semantic analysis - void semantic2(); // pass 2 semantic analysis - void semantic3(); // pass 3 semantic analysis + void semantic(); // semantic analysis + void semantic2(); // pass 2 semantic analysis + void semantic3(); // pass 3 semantic analysis void inlineScan(); // scan for functions to inline void setHdrfile(); // set hdrfile member void genhdrfile(); // generate D import file diff --git a/dmd/mtype.c b/dmd/mtype.c index 1d572261..34a1627f 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -95,12 +95,6 @@ int REALALIGNSIZE = 2; int Tsize_t = Tuns32; int Tptrdiff_t = Tint32; -#if _WIN32 && !(defined __MINGW32__ || defined _MSC_VER) -static double zero = 0; -double Port::nan = NAN; -double Port::infinity = 1/zero; -#endif - /***************************** Type *****************************/ ClassDeclaration *Type::typeinfo; @@ -2229,7 +2223,7 @@ int TypeSArray::hasPointers() // Arrays of void contain arbitrary data, which may include pointers return TRUE; else - return next->hasPointers(); + return next->hasPointers(); } /***************************** TypeDArray *****************************/ @@ -2477,7 +2471,7 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc) break; } if (next->isscope()) - error(loc, "cannot have array of scope %s", next->toChars()); + error(loc, "cannot have array of auto %s", next->toChars()); return merge(); } @@ -2899,7 +2893,7 @@ int Type::covariant(Type *t) size_t dim1 = !t1->parameters ? 0 : t1->parameters->dim; size_t dim2 = !t2->parameters ? 0 : t2->parameters->dim; if (dim1 || dim2) - goto Ldistinct; + goto Ldistinct; } // The argument lists match @@ -3038,8 +3032,8 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd case LINKpascal: p = "Pascal "; break; case LINKcpp: p = "C++ "; break; - // LDC - case LINKintrinsic: p = "Intrinsic"; break; + // LDC + case LINKintrinsic: p = "Intrinsic"; break; default: assert(0); @@ -3474,14 +3468,14 @@ Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident) #endif if (ident == Id::ptr) { - e = new GEPExp(e->loc, e, ident, 0); + e = new GEPExp(e->loc, e, ident, 0); e->type = tvoidptr; return e; } else if (ident == Id::funcptr) { - e = new GEPExp(e->loc, e, ident, 1); - e->type = tvoidptr; + e = new GEPExp(e->loc, e, ident, 1); + e->type = tvoidptr; return e; } else @@ -4021,7 +4015,7 @@ Dsymbol *TypeInstance::toDsymbol(Scope *sc) if (global.endGagging(errors)) return NULL; - } + } else resolve(loc, sc, &e, &t, &s); @@ -4423,6 +4417,7 @@ Expression *TypeEnum::defaultInit(Loc loc) int TypeEnum::isZeroInit(Loc loc) { + //printf("TypeEnum::isZeroInit() '%s'\n", toChars()); if (!sym->isdone && sym->scope) { // Enum is forward referenced. We need to resolve the whole thing. sym->semantic(NULL); @@ -4961,7 +4956,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) { if (vd->init->isVoidInitializer()) e = NULL; else - e = vd->init->toExpression(); + e = vd->init->toExpression(); } else e = vd->type->defaultInitLiteral(); @@ -5503,6 +5498,29 @@ TypeTuple::TypeTuple(Expressions *exps) this->arguments = arguments; } +/******************************************* + * Type tuple with 0, 1 or 2 types in it. + */ +TypeTuple::TypeTuple() + : Type(Ttuple, NULL) +{ + arguments = new Parameters(); +} + +TypeTuple::TypeTuple(Type *t1) + : Type(Ttuple, NULL) +{ + arguments = new Parameters(); + arguments->push(new Parameter(0, t1, NULL, NULL)); +} + +TypeTuple::TypeTuple(Type *t1, Type *t2) + : Type(Ttuple, NULL) +{ + arguments = new Parameters(); + arguments->push(new Parameter(0, t1, NULL, NULL)); + arguments->push(new Parameter(0, t2, NULL, NULL)); +} Type *TypeTuple::syntaxCopy() { Parameters *args = Parameter::arraySyntaxCopy(arguments); diff --git a/dmd/mtype.h b/dmd/mtype.h index 44aac0f1..a54607fd 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -50,12 +50,11 @@ struct Parameter; #if IN_GCC union tree_node; typedef union tree_node TYPE; typedef TYPE type; -#endif - -#if IN_DMD +#else typedef struct TYPE type; -struct Symbol; #endif +struct Symbol; +struct TypeTuple; enum TY { @@ -270,6 +269,7 @@ struct Type : Object virtual Type *reliesOnTident(); virtual Expression *toExpression(); virtual int hasPointers(); + virtual TypeTuple *toArgTypes(); Type *next; Type *nextOf() { return next; } @@ -359,6 +359,7 @@ struct TypeBasic : Type Expression *defaultInit(Loc loc); int isZeroInit(Loc loc); int builtinTypeInfo(); + TypeTuple *toArgTypes(); // For eliminating dynamic_cast TypeBasic *isTypeBasic(); @@ -398,6 +399,7 @@ struct TypeSArray : TypeArray TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *toExpression(); int hasPointers(); + TypeTuple *toArgTypes(); #if IN_DMD type *toCtype(); @@ -424,6 +426,7 @@ struct TypeDArray : TypeArray int builtinTypeInfo(); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); #if IN_DMD type *toCtype(); @@ -449,6 +452,7 @@ struct TypeAArray : TypeArray int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); #if IN_DMD // Back end @@ -473,6 +477,7 @@ struct TypePointer : Type int isZeroInit(Loc loc); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); #if IN_DMD type *toCtype(); @@ -500,7 +505,11 @@ struct TypeFunction : Type { Parameters *parameters; // function parameters int varargs; // 1: T t, ...) style for variable number of arguments + // if extern (C) then this is C style va_args + // if extern (D) then D style va_args // 2: T t ...) style for variable number of arguments + // where the args are stored in a local, and a + // dynamic array is passed to the function enum LINK linkage; // calling convention int inuse; @@ -549,6 +558,7 @@ struct TypeDelegate : Type TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); int hasPointers(); + TypeTuple *toArgTypes(); #if IN_DMD type *toCtype(); @@ -642,6 +652,7 @@ struct TypeStruct : Type MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -661,10 +672,10 @@ struct TypeEnum : Type EnumDeclaration *sym; TypeEnum(EnumDeclaration *sym); + Type *syntaxCopy(); d_uns64 size(Loc loc); unsigned alignsize(); char *toChars(); - Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); Dsymbol *toDsymbol(Scope *sc); void toDecoBuffer(OutBuffer *buf, bool mangle); @@ -682,6 +693,10 @@ struct TypeEnum : Type MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); +#if CPP_MANGLE + void toCppMangle(OutBuffer *buf, CppMangleState *cms); +#endif #if IN_DMD type *toCtype(); @@ -722,6 +737,7 @@ struct TypeTypedef : Type MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); #if IN_DMD type *toCtype(); @@ -752,6 +768,7 @@ struct TypeClass : Type int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); int builtinTypeInfo(); #if DMDV2 Type *toHeadMutable(); @@ -774,6 +791,9 @@ struct TypeTuple : Type TypeTuple(Parameters *arguments); TypeTuple(Expressions *exps); + TypeTuple(); + TypeTuple(Type *t1); + TypeTuple(Type *t1, Type *t2); Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); int equals(Object *o); diff --git a/dmd/parse.c b/dmd/parse.c index 4065caee..3bf1b96b 100644 --- a/dmd/parse.c +++ b/dmd/parse.c @@ -388,8 +388,8 @@ Dsymbols *Parser::parseDeclDefs(int once) case TOKalign: { unsigned n; - // LDC better align code locations - Loc alignloc = loc; + // LDC better align code locations + Loc alignloc = loc; s = NULL; nextToken(); @@ -685,11 +685,11 @@ enum LINK Parser::parseLinkage() } else if (id == Id::System) { - // LDC we configure target at runtime - if (global.params.os == OSWindows) - link = LINKwindows; - else - link = LINKc; + // LDC we configure target at runtime + if (global.params.os == OSWindows) + link = LINKwindows; + else + link = LINKc; } else { @@ -2012,7 +2012,7 @@ Type *Parser::parseBasicType2(Type *t) //printf("it's an associative array\n"); index = parseBasicType(); - index = parseDeclarator(index, NULL); // [ type ] + index = parseDeclarator(index, NULL); // [ type ] check(TOKrbracket); ta = new TypeAArray(t, index); } @@ -3655,7 +3655,7 @@ Statement *Parser::parseStatement(int flags) } break; } - s = new AsmBlockStatement(loc, statements); + s = new AsmBlockStatement(loc, statements); nextToken(); break; } @@ -4494,6 +4494,7 @@ Expression *Parser::parsePrimaryExp() token.value == TOKsuper || token.value == TOKenum || token.value == TOKinterface || + token.value == TOKargTypes || #if DMDV2 token.value == TOKconst && peek(&token)->value == TOKrparen || token.value == TOKinvariant && peek(&token)->value == TOKrparen || diff --git a/dmd/scope.c b/dmd/scope.c index bbabc0c9..86852584 100644 --- a/dmd/scope.c +++ b/dmd/scope.c @@ -16,9 +16,9 @@ #include "mars.h" #include "init.h" #include "identifier.h" +#include "scope.h" #include "attrib.h" #include "dsymbol.h" -#include "scope.h" #include "declaration.h" #include "aggregate.h" #include "module.h" diff --git a/dmd/statement.c b/dmd/statement.c index 3219b56b..e5bd31ef 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -269,9 +269,9 @@ void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } else { - buf->writeByte(';'); - if (!hgs->FLinit.init) - buf->writenl(); + buf->writeByte(';'); + if (!hgs->FLinit.init) + buf->writenl(); } } @@ -1727,9 +1727,9 @@ Statement *ForeachStatement::semantic(Scope *sc) Expression *ec; Expression *e; Parameter *a; - TypeDelegate* dgty; - TypeDelegate* dgty2; - TypeDelegate* fldeTy; + TypeDelegate* dgty; + TypeDelegate* dgty2; + TypeDelegate* fldeTy; Type *tret = func->type->nextOf(); @@ -1838,10 +1838,10 @@ Statement *ForeachStatement::semantic(Scope *sc) FuncDeclaration *fdapply; if (dim == 2) { fdapply = aaApply2_fd; - fldeTy = aaApply2_dg; + fldeTy = aaApply2_dg; } else { fdapply = aaApply_fd; - fldeTy = aaApply_dg; + fldeTy = aaApply_dg; } ec = new VarExp(0, fdapply); Expressions *exps = new Expressions(); @@ -2937,7 +2937,6 @@ Statement *CaseStatement::semantic(Scope *sc) { SwitchStatement *sw = sc->sw; //printf("CaseStatement::semantic() %s\n", toChars()); - exp = exp->semantic(sc); if (sw) { @@ -3126,7 +3125,6 @@ Statement *DefaultStatement::syntaxCopy() Statement *DefaultStatement::semantic(Scope *sc) { //printf("DefaultStatement::semantic()\n"); - if (sc->sw) { if (sc->sw->sdefault) @@ -4098,7 +4096,7 @@ int TryCatchStatement::blockExit(bool mustNotThrow) if (id == Id::Object) { result &= ~BEthrow; - } + } } if (mustNotThrow && (result & BEthrow)) { @@ -4635,6 +4633,9 @@ LabelDsymbol::LabelDsymbol(Identifier *ident) : Dsymbol(ident) { statement = NULL; +#if IN_GCC + asmLabelNum = 0; +#endif } LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? diff --git a/dmd/statement.h b/dmd/statement.h index 27406c1b..1fc7c24f 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -143,7 +143,7 @@ struct Statement : Object virtual CompoundStatement *isCompoundStatement() { return NULL; } virtual ReturnStatement *isReturnStatement() { return NULL; } virtual IfStatement *isIfStatement() { return NULL; } - virtual CaseStatement* isCaseStatement() { return NULL; } + virtual CaseStatement *isCaseStatement() { return NULL; } virtual DefaultStatement *isDefaultStatement() { return NULL; } virtual LabelStatement* isLabelStatement() { return NULL; } @@ -883,6 +883,9 @@ struct LabelStatement : Statement struct LabelDsymbol : Dsymbol { LabelStatement *statement; +#if IN_GCC + unsigned asmLabelNum; // GCC-specific +#endif LabelDsymbol(Identifier *ident); LabelDsymbol *isLabel(); diff --git a/dmd/struct.c b/dmd/struct.c index b320fdb8..81c2a2e8 100644 --- a/dmd/struct.c +++ b/dmd/struct.c @@ -229,7 +229,7 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) memalignsize = sc->structalign; if (alignsize < memalignsize) alignsize = memalignsize; - //printf("\talignsize = %d\n", alignsize); + //printf("\t%s: alignsize = %d\n", toChars(), alignsize); v->storage_class |= STCfield; //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); @@ -298,6 +298,7 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id) hasIdentityAssign = 0; cpctor = NULL; postblit = NULL; + eq = NULL; #endif // For forward references @@ -320,9 +321,9 @@ void StructDeclaration::semantic(Scope *sc) { Scope *sc2; - //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); + //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", this, toChars(), sizeok); - //static int count; if (++count == 20) *(char*)0=0; + //static int count; if (++count == 20) halt(); assert(type); if (!members) // if forward reference @@ -479,6 +480,40 @@ void StructDeclaration::semantic(Scope *sc) } #endif #if DMDV2 + /* Try to find the opEquals function. Build it if necessary. + */ + TypeFunction *tfeqptr; + { // bool opEquals(const T*) const; + Parameters *parameters = new Parameters; +#if STRUCTTHISREF + // bool opEquals(ref const T) const; + Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL); +#else + // bool opEquals(const T*) const; + Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL); +#endif + + parameters->push(param); + tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd); + tfeqptr->mod = MODconst; + tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2); + + Dsymbol *s = search_function(this, Id::eq); + FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; + if (fdx) + { + eq = fdx->overloadExactMatch(tfeqptr); + if (!eq) + fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars()); + } + + TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL; + // BUG: should also check that td is a function template, not just a template + + if (!eq && !td) + eq = buildOpEquals(sc2); + } + dtor = buildDtor(sc2); postblit = buildPostBlit(sc2); cpctor = buildCpCtor(sc2); diff --git a/dmd/template.c b/dmd/template.c index a692a0b3..9c3305b8 100644 --- a/dmd/template.c +++ b/dmd/template.c @@ -13,14 +13,11 @@ #include #include -#if !IN_LLVM -#endif #include "root.h" #include "aav.h" #include "rmem.h" #include "stringtable.h" -#include "mars.h" -#include "identifier.h" + #include "mtype.h" #include "template.h" #include "init.h" @@ -30,6 +27,9 @@ #include "aggregate.h" #include "declaration.h" #include "dsymbol.h" +#include "mars.h" +#include "dsymbol.h" +#include "identifier.h" #include "hdrgen.h" #if WINDOWS_SEH @@ -235,7 +235,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) { if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) goto Lnomatch; - } + } else if (u1) { if (!u2) @@ -1555,7 +1555,7 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("foo "); #endif if (hgs->ddoc) - buf->writestring(kind()); + buf->writestring(kind()); else buf->writestring("template"); buf->writeByte(' '); @@ -1822,7 +1822,7 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame TypeSArray *tp = (TypeSArray *)tparam; if (tp->dim->op == TOKvar && ((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter) - { + { id = ((VarExp *)tp->dim)->var->ident; } else if (dim->toInteger() != tp->dim->toInteger()) @@ -1833,7 +1833,7 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame TypeAArray *tp = (TypeAArray *)tparam; if (tp->index->ty == Tident && ((TypeIdentifier *)tp->index)->idents.dim == 0) - { + { id = ((TypeIdentifier *)tp->index)->ident; } } @@ -1842,28 +1842,28 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame // This code matches code in TypeInstance::deduceType() int i = templateIdentifierLookup(id, parameters); if (i == -1) - goto Lnomatch; + goto Lnomatch; TemplateParameter *tprm = parameters->tdata()[i]; TemplateValueParameter *tvp = tprm->isTemplateValueParameter(); if (!tvp) goto Lnomatch; Expression *e = (Expression *)dedtypes->tdata()[i]; if (e) - { + { if (!dim->equals(e)) - goto Lnomatch; - } - else + goto Lnomatch; + } + else { Type *vt = tvp->valType->semantic(0, sc); MATCH m = (MATCH)dim->implicitConvTo(vt); if (!m) goto Lnomatch; dedtypes->tdata()[i] = dim; - } - return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); - } - } + } + return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); + } + } return Type::deduceType(sc, tparam, parameters, dedtypes); Lnomatch: @@ -3655,7 +3655,7 @@ void TemplateInstance::semantic(Scope *sc) if (m->semanticRun >= 3) { dosemantic3 = 1; - } + } } for (size_t i = 0; 1; i++) { @@ -3866,10 +3866,10 @@ void TemplateInstance::semantic(Scope *sc) assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); target_symbol_list->remove(target_symbol_list_idx); } - semanticRun = 0; - inst = NULL; - } + semanticRun = 0; + inst = NULL; } + } #if LOG printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); @@ -4302,9 +4302,9 @@ int TemplateInstance::hasNestedArgs(Objects *args) (ad && ad->isnested) || (d && !d->isDataseg() && #if DMDV2 - !(d->storage_class & STCmanifest) && + !(d->storage_class & STCmanifest) && #endif - (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && + (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && !isTemplateMixin() )) { @@ -4691,7 +4691,7 @@ void TemplateInstance::toObjFile(int multiobj) if (multiobj) // Append to list of object files to be written later //obj_append(this); - assert(0 && "multiobj"); + assert(0 && "multiobj"); else { for (size_t i = 0; i < members->dim; i++) diff --git a/dmd/template.h b/dmd/template.h index 77780a03..77f1cee7 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -384,4 +384,3 @@ Dsymbol *getDsymbol(Object *o); void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg); #endif /* DMD_TEMPLATE_H */ - diff --git a/dmd/utf.c b/dmd/utf.c index 8aac2ee7..78f8cd4a 100644 --- a/dmd/utf.c +++ b/dmd/utf.c @@ -1,5 +1,5 @@ // utf.c -// Copyright (c) 2003-2010 by Digital Mars +// Copyright (c) 2003-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com