asm关键字作为C中的标识符名称?

时间:2018-12-11 20:29:32

标签: c assembly makefile cmake keyword

I've seen a project,它使用asm关键字作为变量名,并且代码在Makefile上使用提供的Linux可以正常编译:

int
main(int ac, char *av[])
{
    struct TMap *tm;
    FILE *inf, *hf;
    char *f, *sep;
    int c, asm; // <---

    asm = Defasm;
    // ...
}

这是整个Makefile

BIN = qbe

V = @
OBJDIR = obj

SRC      = main.c util.c parse.c cfg.c mem.c ssa.c alias.c load.c copy.c \
           fold.c live.c spill.c rega.c gas.c
AMD64SRC = amd64/targ.c amd64/sysv.c amd64/isel.c amd64/emit.c
ARM64SRC = arm64/targ.c arm64/abi.c arm64/isel.c arm64/emit.c
SRCALL   = $(SRC) $(AMD64SRC) $(ARM64SRC)

AMD64OBJ = $(AMD64SRC:%.c=$(OBJDIR)/%.o)
ARM64OBJ = $(ARM64SRC:%.c=$(OBJDIR)/%.o)
OBJ      = $(SRC:%.c=$(OBJDIR)/%.o) $(AMD64OBJ) $(ARM64OBJ)

CFLAGS += -Wall -Wextra -std=c99 -g -pedantic

$(OBJDIR)/$(BIN): $(OBJ) $(OBJDIR)/timestamp
    @test -z "$(V)" || echo "ld $@"
    $(V)$(CC) $(LDFLAGS) $(OBJ) -o $@

$(OBJDIR)/%.o: %.c $(OBJDIR)/timestamp
    @test -z "$(V)" || echo "cc $<"
    $(V)$(CC) $(CFLAGS) -c $< -o $@

$(OBJDIR)/timestamp:
    @mkdir -p $(OBJDIR)
    @mkdir -p $(OBJDIR)/amd64
    @mkdir -p $(OBJDIR)/arm64
    @touch $@

$(OBJ): all.h ops.h
$(AMD64OBJ): amd64/all.h
$(ARM64OBJ): arm64/all.h
obj/main.o: config.h

config.h:
    @case `uname` in                               \
    *Darwin*)                                      \
        echo "#define Defasm Gasmacho";        \
        echo "#define Deftgt T_amd64_sysv";    \
        ;;                                     \
    *)                                             \
        echo "#define Defasm Gaself";          \
        case `uname -m` in                     \
        *aarch64*)                             \
            echo "$define Deftgt T_arm64"; \
            ;;                             \
        *)                                     \
            echo "#define Deftgt T_amd64_sysv";\
            ;;                             \
        esac                                   \
        ;;                                     \
    esac > $@

install: $(OBJDIR)/$(BIN)
    mkdir -p "$(DESTDIR)/$(PREFIX)/bin/"
    cp $< "$(DESTDIR)/$(PREFIX)/bin/"

uninstall:
    rm -f "$(DESTDIR)/$(PREFIX)/bin/$(BIN)"

clean:
    rm -fr $(OBJDIR)

clean-gen: clean
    rm -f config.h

check: $(OBJDIR)/$(BIN)
    tools/test.sh all

check-arm64: $(OBJDIR)/$(BIN)
    TARGET=arm64 tools/test.sh all

src:
    @echo $(SRCALL)

80:
    @for F in $(SRCALL);                       \
    do                                         \
        awk "{                             \
            gsub(/\\t/, \"        \"); \
            if (length(\$$0) > $@)     \
                printf(\"$$F:%d: %s\\n\", NR, \$$0); \
        }" < $$F;                          \
    done

.PHONY: clean clean-gen check check-arm64 src 80 install uninstall

我想知道如何实现编译器将asm用作变量名(忽略这样做的错误样式这一事实)。我尝试将Makefile移植到CMakeLists.txt,但是由于asm的无效用法,编译器引发了错误。如何在不更改代码的情况下解决此问题?我已经像C99一样强行使用Makefile标准,并使用了相同的C编译器标志,但这无济于事:

cmake_minimum_required(VERSION 3.10.2)
project(qbe C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-Wall -Wextra -std=c99 -g -pedantic")

include_directories(amd64)

add_executable(qbe
        amd64/all.h
        amd64/emit.c
        amd64/isel.c
        amd64/sysv.c
        amd64/targ.c
        alias.c
        all.h
        cfg.c
        copy.c
        fold.c
        gas.c
        live.c
        load.c
        main.c
        mem.c
        ops.h
        parse.c
        rega.c
        spill.c
        ssa.c
        util.c)

由于CMake的支持,我想使用IDE

2 个答案:

答案 0 :(得分:4)

asm不是标准C的关键字,也不是保留的标识符,尽管是the standard recognizes it as a common extension。该标准进一步指出

  

包含任何可能导致严格符合的扩展名   程序变为无效会导致实现不合格。   此类扩展的示例包括新关键字,额外的库函数   在标准标头或预定义的宏中声明的名称   不是以下划线开头。

这在Annex J中,它是非规范性的,但是它仅总结了可以从规范性文本中得出的结论。因此,符合标准的实现不会因为使用asm作为标识符而拒绝代码。

例如,我发现在使用GCC支持的任何严格一致性模式(asm-std=c89或{{1})时,GCC都接受使用-std=c99作为标识符}),但默认情况下会出现错误或通过专门启用的GNU扩展(例如,-std=c11)将其拒绝。如果您使用的是其他编译器,则如果可能的话,您将需要查阅其文档以获取如何符合该领域标准的要求。

附录

对于为什么您的CMake尝试失败的原因,-std=gnu11属性没有按照您认为的那样做。它告诉CMake在可能的情况下选择提供C版本指定版本功能的编译器选项,但不要求对该标准严格遵守。文档专门假设它会导致在某些情况下使用CMAKE_C_STANDARD选项,并且该选项或类似的包含选项会产生与您想要的相反的效果。

答案 1 :(得分:3)

asm不是标准的C关键字。合格的C编译器可能不会拒绝编译使用asm作为标识符的程序。

使用-std=c99明确选择标准也会删除asm关键字。但是,您可以继续使用__asm__,因为实现中始终将所有以两个下划线开头的名称保留为 any 使用。


但是,它仍然是非常糟糕的样式,因为 C99 ,C11和C17修订版 do 都将其称为common extension