Changeset 149d297


Ignore:
Timestamp:
Mar 9, 2017, 10:47:08 PM (5 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
68ac32e, a9b657a
Parents:
6152c81 (diff), 7b2c2c5f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge

Files:
4 deleted
13 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    r6152c81 r149d297  
    3030
    3131src/prelude/builtins.cf
     32src/prelude/builtins.c
    3233src/prelude/extras.cf
    3334src/prelude/bootloader.c
     
    3637# generated by bison and lex from cfa.yy and lex.ll, respectively
    3738src/Parser/parser.output
     39src/Parser/lex.cc
     40src/Parser/parser.cc
     41src/Parser/parser.h
    3842
    3943# generated by xfig for user manual
  • Jenkinsfile

    r6152c81 r149d297  
    227227        switch( arch ) {
    228228                case 'x64':
    229                         return '--host=x86_64 CXXFLAGS="-m64" CFAFLAGS="-m64"'
     229                        return '--host=x86_64'
    230230                break
    231231                case 'x86':
    232                         return '--host=i386   CXXFLAGS="-m32" CFAFLAGS="-m32"'
     232                        return '--host=i386'
    233233                break
    234234                default :
  • configure

    r6152c81 r149d297  
    644644CXXFLAGS
    645645CXX
     646CFA_FLAGS
    646647MACHINE_TYPE
    647648host_os
     
    653654build_cpu
    654655build
    655 CFA_FLAGS
    656656CFA_LIBDIR
    657657CFA_BINDIR
     
    742742enable_silent_rules
    743743enable_maintainer_mode
     744with_cfa_name
    744745with_backend_compiler
    745746enable_target_release
     
    13981399  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
    13991400  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
     1401  --with-cfa-name=NAME     NAME too which cfa will be installed
    14001402  --with-backend-compiler=PROGRAM     PROGRAM that performs the final code compilation (must be gcc-compatible)
    14011403
     
    30033005
    30043006# Allow program name tansformation
    3005 # will fille program_transform_name with appropriate sed regex
    3006 
    3007 #autoconf escapes $ and \ since automake wiill un-escape them.
    3008 #Since we need to use the sed transform in autoconf we need to manualy un-escape these characters
    3009 name_transform=`echo ${program_transform_name} | sed 's/\\$\\$/\\$/g' | sed 's/\\\\\\\/\\\/g'`
    3010 cfa_name=`echo cfa | sed ${name_transform}`
    3011 cc1_name=`echo cc1 | sed ${name_transform}`
    3012 cpp_name=`echo cfa-cpp | sed ${name_transform}`
     3007# will fill program_transform_name with appropriate sed regex
     3008
    30133009
    30143010#Trasforming cc1 will break compilation
    3015 if ! test "${cc1_name}" = "cc1"; then
    3016     as_fn_error $? "Program transform must not modify cc1.
    3017                 --program-sufix and --program-prefix not supported.
    3018                 Use -program-transform-name='s/cfa$/[Desired name here]/' instead" "$LINENO" 5
    3019 fi
    3020 #We could support transforming cfa-cpp but since it is located in a unique subfolder we don't need to
    3021 if ! test "${cpp_name}" = "cfa-cpp"; then
    3022     as_fn_error $? "Program transform must not modify cfa-cpp.
    3023                 --program-sufix and --program-prefix not supported.
    3024                 Use -program-transform-name='s/cfa$/[Desired name here]/' instead" "$LINENO" 5
    3025 fi
     3011if test "${program_transform_name}" = ""; then
     3012    as_fn_error $? "Program transform not supported.
     3013                Use --with-cfa-name='[Desired name here]' instead" "$LINENO" 5
     3014fi
     3015
     3016
     3017# Check whether --with-cfa-name was given.
     3018if test "${with_cfa_name+set}" = set; then :
     3019  withval=$with_cfa_name; cfa_name=$withval
     3020else
     3021  cfa_name="cfa"
     3022fi
     3023
    30263024
    30273025#Define the new name of the installed command
     
    33043302
    33053303
    3306 
    3307 cat >>confdefs.h <<_ACEOF
    3308 #define CFA_FLAGS "${CFAFLAGS}"
    3309 _ACEOF
    3310 
    3311 CFA_FLAGS=${CFAFLAGS}
    3312 
    3313 
    33143304# Make sure we can run config.sub.
    33153305$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
     
    33843374
    33853375MACHINE_TYPE=$host_cpu
     3376
     3377
     3378if ! test "$host_cpu" = "$build_cpu"; then
     3379        case $host_cpu in
     3380                i386)
     3381                        CFLAGS+="-m32"
     3382                        CXXFLAGS+="-m32"
     3383                        CFAFLAGS+="-m32"
     3384                        LDFLAGS+="-m32"
     3385                        ;;
     3386                i686)
     3387                        CFLAGS+="-m32"
     3388                        CXXFLAGS+="-m32"
     3389                        CFAFLAGS+="-m32"
     3390                        LDFLAGS+="-m32"
     3391                        ;;
     3392                x86_64)
     3393                        CFLAGS+="-m64"
     3394                        CXXFLAGS+="-m64"
     3395                        CFAFLAGS+="-m64"
     3396                        LDFLAGS+="-m64"
     3397                        ;;
     3398        esac
     3399fi
     3400
     3401
     3402cat >>confdefs.h <<_ACEOF
     3403#define CFA_FLAGS "${CFAFLAGS}"
     3404_ACEOF
     3405
     3406CFA_FLAGS=${CFAFLAGS}
    33863407
    33873408
  • configure.ac

    r6152c81 r149d297  
    1919
    2020# Allow program name tansformation
    21 # will fille program_transform_name with appropriate sed regex
     21# will fill program_transform_name with appropriate sed regex
    2222AC_ARG_PROGRAM
    23 #autoconf escapes $ and \ since automake wiill un-escape them.
    24 #Since we need to use the sed transform in autoconf we need to manualy un-escape these characters
    25 name_transform=`echo ${program_transform_name} | sed 's/\\$\\$/\\$/g' | sed 's/\\\\\\\/\\\/g'`
    26 cfa_name=`echo cfa | sed ${name_transform}`
    27 cc1_name=`echo cc1 | sed ${name_transform}`
    28 cpp_name=`echo cfa-cpp | sed ${name_transform}`
    2923
    3024#Trasforming cc1 will break compilation
    31 if ! test "${cc1_name}" = "cc1"; then
    32     AC_MSG_ERROR([Program transform must not modify cc1.
    33                 --program-sufix and --program-prefix not supported.
    34                 Use -program-transform-name='s/cfa$/[[Desired name here]]/' instead])
    35 fi
    36 #We could support transforming cfa-cpp but since it is located in a unique subfolder we don't need to
    37 if ! test "${cpp_name}" = "cfa-cpp"; then
    38     AC_MSG_ERROR([Program transform must not modify cfa-cpp.
    39                 --program-sufix and --program-prefix not supported.
    40                 Use -program-transform-name='s/cfa$/[[Desired name here]]/' instead])
    41 fi
     25if test "${program_transform_name}" = ""; then
     26    AC_MSG_ERROR([Program transform not supported.
     27                Use --with-cfa-name='[[Desired name here]]' instead])
     28fi
     29
     30AC_ARG_WITH(cfa-name,
     31        [  --with-cfa-name=NAME     NAME too which cfa will be installed],
     32        cfa_name=$withval, cfa_name="cfa")
    4233
    4334#Define the new name of the installed command
     
    178169AC_SUBST(CFA_LIBDIR, ${cfa_libdir})
    179170
     171AC_CANONICAL_BUILD
     172AC_CANONICAL_HOST
     173AC_SUBST([MACHINE_TYPE],[$host_cpu])
     174
     175if ! test "$host_cpu" = "$build_cpu"; then
     176        case $host_cpu in
     177                i386)
     178                        CFLAGS+="-m32"
     179                        CXXFLAGS+="-m32"
     180                        CFAFLAGS+="-m32"
     181                        LDFLAGS+="-m32"
     182                        ;;
     183                i686)
     184                        CFLAGS+="-m32"
     185                        CXXFLAGS+="-m32"
     186                        CFAFLAGS+="-m32"
     187                        LDFLAGS+="-m32"
     188                        ;;
     189                x86_64)
     190                        CFLAGS+="-m64"
     191                        CXXFLAGS+="-m64"
     192                        CFAFLAGS+="-m64"
     193                        LDFLAGS+="-m64"
     194                        ;;
     195        esac
     196fi
     197
    180198AC_DEFINE_UNQUOTED(CFA_FLAGS, "${CFAFLAGS}", [compilation flags for cfa libraries and test programs.])
    181199AC_SUBST(CFA_FLAGS, ${CFAFLAGS})
    182 
    183 AC_CANONICAL_HOST
    184 AC_SUBST([MACHINE_TYPE],[$host_cpu])
    185200
    186201# Checks for programs.
  • src/CodeTools/DeclStats.cc

    r6152c81 r149d297  
    186186                        auto& args = expr->get_args();
    187187                        unsigned fanout = args.size();
     188                       
    188189                        ++exprs_by_fanout_at_depth[ std::make_pair(depth, fanout) ];
    189190                        for ( Expression* arg : args ) {
  • src/GenPoly/InstantiateGeneric.cc

    r6152c81 r149d297  
    226226
    227227                        if ( (*baseParam)->isComplete() ) {
    228                                 // substitute parameter for complete (otype or sized dtype) type; makes the struct concrete or dynamic depending on the parameter
    229                                 out.push_back( paramType->clone() );
     228                                // substitute parameter for complete (otype or sized dtype) type
     229                                int pointerLevels = 0;
     230                                if ( hasPolyBase( paramType->get_type(), &pointerLevels ) && pointerLevels > 0 ) {
     231                                        // Make a void* with equivalent nesting
     232                                        Type* voidPtr = new VoidType( Type::Qualifiers() );
     233                                        while ( pointerLevels > 0 ) {
     234                                                // Just about data layout, so qualifiers *shouldn't* matter
     235                                                voidPtr = new PointerType( Type::Qualifiers(), voidPtr );
     236                                                --pointerLevels;
     237                                        }
     238                                        out.push_back( new TypeExpr( voidPtr ) );
     239                                } else {
     240                                        // Just clone parameter type
     241                                        out.push_back( paramType->clone() );
     242                                }
     243                                // make the struct concrete or dynamic depending on the parameter
    230244                                gt |= isPolyType( paramType->get_type() ) ? genericType::dynamic : genericType::concrete;
    231245                        } else switch ( (*baseParam)->get_kind() ) {
  • src/driver/Makefile.am

    r6152c81 r149d297  
    2828endif
    2929
    30 bin_PROGRAMS = cfa
     30noinst_PROGRAMS = cfa
    3131cfa_SOURCES = cfa.cc
     32
     33install-exec-hook:
     34        @echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa '$(CFA_BINDIR)/$(CFA_NAME)'"; \
     35        $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa $(CFA_BINDIR)/$(CFA_NAME) || exit $$?
     36
     37uninstall-hook:
     38        @echo " ( cd '$(CFA_BINDIR)' && rm -f $(CFA_NAME) )"; \
     39        cd "$(CFA_BINDIR)" && rm -f $(CFA_NAME)
    3240
    3341# put into lib for now
     
    3644cc1_SOURCES = cc1.cc
    3745
    38 MAINTAINERCLEANFILES = @CFA_PREFIX@/bin/${bin_PROGRAMS} @CFA_PREFIX@/lib/${cc1lib_PROGRAMS}
     46MAINTAINERCLEANFILES = $(CFA_BINDIR)/$(CFA_NAME) @CFA_PREFIX@/lib/${cc1lib_PROGRAMS}
  • src/driver/Makefile.in

    r6152c81 r149d297  
    4141@BUILD_DEBUG_TRUE@am__append_2 = -DHAVE_LIBCFA_DEBUG
    4242@BUILD_RELEASE_TRUE@am__append_3 = -DHAVE_LIBCFA_RELEASE
    43 bin_PROGRAMS = cfa$(EXEEXT)
     43noinst_PROGRAMS = cfa$(EXEEXT)
    4444cc1lib_PROGRAMS = cc1$(EXEEXT)
    4545subdir = src/driver
     
    5353CONFIG_CLEAN_FILES =
    5454CONFIG_CLEAN_VPATH_FILES =
    55 am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cc1libdir)"
    56 PROGRAMS = $(bin_PROGRAMS) $(cc1lib_PROGRAMS)
     55am__installdirs = "$(DESTDIR)$(cc1libdir)"
     56PROGRAMS = $(cc1lib_PROGRAMS) $(noinst_PROGRAMS)
    5757am_cc1_OBJECTS = cc1.$(OBJEXT)
    5858cc1_OBJECTS = $(am_cc1_OBJECTS)
     
    215215cc1libdir = ${CFA_LIBDIR}
    216216cc1_SOURCES = cc1.cc
    217 MAINTAINERCLEANFILES = @CFA_PREFIX@/bin/${bin_PROGRAMS} @CFA_PREFIX@/lib/${cc1lib_PROGRAMS}
     217MAINTAINERCLEANFILES = $(CFA_BINDIR)/$(CFA_NAME) @CFA_PREFIX@/lib/${cc1lib_PROGRAMS}
    218218all: all-am
    219219
     
    250250        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    251251$(am__aclocal_m4_deps):
    252 install-binPROGRAMS: $(bin_PROGRAMS)
    253         @$(NORMAL_INSTALL)
    254         test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
    255         @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
    256         for p in $$list; do echo "$$p $$p"; done | \
    257         sed 's/$(EXEEXT)$$//' | \
    258         while read p p1; do if test -f $$p; \
    259           then echo "$$p"; echo "$$p"; else :; fi; \
    260         done | \
    261         sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
    262             -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
    263         sed 'N;N;N;s,\n, ,g' | \
    264         $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
    265           { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
    266             if ($$2 == $$4) files[d] = files[d] " " $$1; \
    267             else { print "f", $$3 "/" $$4, $$1; } } \
    268           END { for (d in files) print "f", d, files[d] }' | \
    269         while read type dir files; do \
    270             if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
    271             test -z "$$files" || { \
    272               echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
    273               $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
    274             } \
    275         ; done
    276 
    277 uninstall-binPROGRAMS:
    278         @$(NORMAL_UNINSTALL)
    279         @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
    280         files=`for p in $$list; do echo "$$p"; done | \
    281           sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
    282               -e 's/$$/$(EXEEXT)/' `; \
    283         test -n "$$list" || exit 0; \
    284         echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
    285         cd "$(DESTDIR)$(bindir)" && rm -f $$files
    286 
    287 clean-binPROGRAMS:
    288         -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
    289252install-cc1libPROGRAMS: $(cc1lib_PROGRAMS)
    290253        @$(NORMAL_INSTALL)
     
    324287clean-cc1libPROGRAMS:
    325288        -test -z "$(cc1lib_PROGRAMS)" || rm -f $(cc1lib_PROGRAMS)
     289
     290clean-noinstPROGRAMS:
     291        -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
    326292cc1$(EXEEXT): $(cc1_OBJECTS) $(cc1_DEPENDENCIES) $(EXTRA_cc1_DEPENDENCIES)
    327293        @rm -f cc1$(EXEEXT)
     
    440406all-am: Makefile $(PROGRAMS)
    441407installdirs:
    442         for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cc1libdir)"; do \
     408        for dir in "$(DESTDIR)$(cc1libdir)"; do \
    443409          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
    444410        done
     
    476442clean: clean-am
    477443
    478 clean-am: clean-binPROGRAMS clean-cc1libPROGRAMS clean-generic \
     444clean-am: clean-cc1libPROGRAMS clean-generic clean-noinstPROGRAMS \
    479445        mostlyclean-am
    480446
     
    503469install-dvi-am:
    504470
    505 install-exec-am: install-binPROGRAMS
    506 
     471install-exec-am:
     472        @$(NORMAL_INSTALL)
     473        $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
    507474install-html: install-html-am
    508475
     
    542509ps-am:
    543510
    544 uninstall-am: uninstall-binPROGRAMS uninstall-cc1libPROGRAMS
    545 
    546 .MAKE: install-am install-strip
    547 
    548 .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
    549         clean-cc1libPROGRAMS clean-generic ctags distclean \
    550         distclean-compile distclean-generic distclean-tags distdir dvi \
    551         dvi-am html html-am info info-am install install-am \
    552         install-binPROGRAMS install-cc1libPROGRAMS install-data \
    553         install-data-am install-dvi install-dvi-am install-exec \
    554         install-exec-am install-html install-html-am install-info \
     511uninstall-am: uninstall-cc1libPROGRAMS
     512        @$(NORMAL_INSTALL)
     513        $(MAKE) $(AM_MAKEFLAGS) uninstall-hook
     514.MAKE: install-am install-exec-am install-strip uninstall-am
     515
     516.PHONY: CTAGS GTAGS all all-am check check-am clean \
     517        clean-cc1libPROGRAMS clean-generic clean-noinstPROGRAMS ctags \
     518        distclean distclean-compile distclean-generic distclean-tags \
     519        distdir dvi dvi-am html html-am info info-am install \
     520        install-am install-cc1libPROGRAMS install-data install-data-am \
     521        install-dvi install-dvi-am install-exec install-exec-am \
     522        install-exec-hook install-html install-html-am install-info \
    555523        install-info-am install-man install-pdf install-pdf-am \
    556524        install-ps install-ps-am install-strip installcheck \
     
    558526        maintainer-clean-generic mostlyclean mostlyclean-compile \
    559527        mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
    560         uninstall-am uninstall-binPROGRAMS uninstall-cc1libPROGRAMS
    561 
     528        uninstall-am uninstall-cc1libPROGRAMS uninstall-hook
     529
     530
     531install-exec-hook:
     532        @echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa '$(CFA_BINDIR)/$(CFA_NAME)'"; \
     533        $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa $(CFA_BINDIR)/$(CFA_NAME) || exit $$?
     534
     535uninstall-hook:
     536        @echo " ( cd '$(CFA_BINDIR)' && rm -f $(CFA_NAME) )"; \
     537        cd "$(CFA_BINDIR)" && rm -f $(CFA_NAME)
    562538
    563539# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • src/libcfa/Makefile.am

    r6152c81 r149d297  
    8181
    8282maintainer-clean-local:
    83         -rm -rf ${includedir}/* ${libdir}/*
     83        -rm -rf ${CFA_INCDIR} ${CFA_LIBDIR}
  • src/libcfa/Makefile.in

    r6152c81 r149d297  
    11611161
    11621162maintainer-clean-local:
    1163         -rm -rf ${includedir}/* ${libdir}/*
     1163        -rm -rf ${CFA_INCDIR} ${CFA_LIBDIR}
    11641164
    11651165# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • src/libcfa/concurrency/CtxSwitch-i386.S

    r6152c81 r149d297  
    5252        movl 4(%esp),%eax
    5353
     54        // Save floating & SSE control words on the stack.
     55
     56        sub    $8,%esp
     57        stmxcsr 0(%esp)         // 4 bytes
     58        fnstcw  4(%esp)         // 2 bytes
     59
    5460        // Save volatile registers on the stack.
    5561
     
    6975        // argument is now at 8 + 12 = 20(%esp)
    7076
    71         movl 20(%esp),%eax
     77        movl 28(%esp),%eax
    7278
    7379        // Load new context from the "to" area.
     
    8187        popl %edi
    8288        popl %ebx
     89
     90        // Load floating & SSE control words from the stack.
     91
     92        fldcw   4(%esp)
     93        ldmxcsr 0(%esp)
     94        add    $8,%esp
    8395
    8496        // Return to thread.
  • src/libcfa/concurrency/CtxSwitch-x86_64.S

    r6152c81 r149d297  
    4747CtxSwitch:
    4848
    49         // Save volatile registers on the stack.
     49        // Save floating & SSE control words on the stack.
    5050
    5151        subq   $8,%rsp
    5252        stmxcsr 0(%rsp)         // 4 bytes
    5353        fnstcw  4(%rsp)         // 2 bytes
     54
     55        // Save volatile registers on the stack.
     56
    5457        pushq %r15
    5558        pushq %r14
     
    7578        popq %r14
    7679        popq %r15
     80
     81        // Load floating & SSE control words from the stack.
     82
    7783        fldcw   4(%rsp)
    7884        ldmxcsr 0(%rsp)
    79         addq $8,%rsp
     85        addq   $8,%rsp
    8086
    8187        // Return to thread.
  • src/libcfa/concurrency/invoke.c

    r6152c81 r149d297  
    9191        struct FakeStack {
    9292            void *fixedRegisters[3];                    // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant)
    93             void *rturn;                                      // where to go on return from uSwitch
     93            uint32_t mxcr;                              // SSE Status and Control bits (control bits are preserved across function calls)
     94            uint16_t fcw;                               // X97 FPU control word (preserved across function calls)
     95            void *rturn;                                // where to go on return from uSwitch
    9496            void *dummyReturn;                          // fake return compiler would have pushed on call to uInvoke
    9597            void *argument[3];                          // for 16-byte ABI, 16-byte alignment starts here
     
    108110      struct FakeStack {
    109111            void *fixedRegisters[5];                    // fixed registers rbx, r12, r13, r14, r15
    110             uint32_t mxcr;                                  // SSE Status and Control bits (control bits are preserved across function calls)
    111             uint16_t fcw;                                   // X97 FPU control word (preserved across function calls)
    112             void *rturn;                                      // where to go on return from uSwitch
     112            uint32_t mxcr;                              // SSE Status and Control bits (control bits are preserved across function calls)
     113            uint16_t fcw;                               // X97 FPU control word (preserved across function calls)
     114            void *rturn;                                // where to go on return from uSwitch
    113115            void *dummyReturn;                          // NULL return address to provide proper alignment
    114116      };
Note: See TracChangeset for help on using the changeset viewer.