Created
May 9, 2012 12:49
-
-
Save nominolo/2644270 to your computer and use it in GitHub Desktop.
Clang Ubuntu compilation error.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
/* | |
This file tests a direct-threaded interpreter with the ability to | |
switch the mode (by modifying the dispatch table). | |
It uses one non-standard feature supported by GCC and Clang on Darwin, | |
namely "Labels as Values" (the syntax "&&label_name"). | |
It compiles fine in GCC and Clang for Mac, but fails on Ubuntu's Clang with | |
duplicated labels: | |
/tmp/cc-wUdEEL.s: Assembler messages: | |
/tmp/cc-wUdEEL.s:46: Error: symbol `.LBA11_interp_send_' is already defined | |
/tmp/cc-wUdEEL.s:54: Error: symbol `.LBA11_interp_send_' is already defined | |
clang: error: assembler command failed with exit code 1 (use -v to see invocation) | |
Clang Ubuntu version: | |
$ clang --version | |
clang version 1.1 (branches/release_27) | |
Target: x86_64-pc-linux-gnu | |
Thread model: posix | |
Clang Mac version: | |
$ clang --version | |
Apple clang version 2.0 (tags/Apple/clang-139) (based on LLVM 2.9svn) | |
Target: x86_64-apple-darwin10 | |
Thread model: posix | |
It works fine with GCC (both Mac and Ubuntu) and llvm-gcc on Ubuntu. | |
$ llvm-gcc --version | |
llvm-gcc (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build) | |
Copyright (C) 2007 Free Software Foundation, Inc. | |
This is free software; see the source for copying conditions. There is NO | |
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
$ gcc --version | |
gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3 | |
Copyright (C) 2009 Free Software Foundation, Inc. | |
This is free software; see the source for copying conditions. There is NO | |
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
*/ | |
typedef void *Impl; | |
typedef enum { | |
OP_STOP, | |
OP_BEEP, | |
OP_MOO, | |
OP__MAX | |
} Opcode; | |
typedef uint8_t Instr; | |
typedef struct _VM { | |
Impl dispatch[OP__MAX]; | |
int *sp; | |
Instr *pc; | |
} VM; | |
Impl dispatch[OP__MAX]; | |
typedef enum { | |
IM_INIT_DISPATCH, | |
IM_RUN, | |
IM_TOGGLE, | |
} InterpMessage; | |
void interp_send(InterpMessage msg, VM *vm) { | |
int *sp; | |
Instr *pc; | |
Impl *dispatch = &vm->dispatch[0]; | |
static const Impl default_dispatch[OP__MAX] = { | |
&&op_stop, &&op_beep, &&op_moo | |
}; | |
switch (msg) { | |
case IM_INIT_DISPATCH: | |
{ | |
int opc; | |
for (opc = 0; opc < OP__MAX; opc++) { | |
dispatch[opc] = default_dispatch[opc]; | |
} | |
return; | |
} | |
case IM_TOGGLE: | |
{ | |
Impl tmp = dispatch[OP_BEEP]; | |
dispatch[OP_BEEP] = dispatch[OP_MOO]; | |
dispatch[OP_MOO] = tmp; | |
return; | |
} | |
default: | |
sp = vm->sp; | |
pc = vm->pc; | |
} | |
#define DISPATCH_NEXT goto *dispatch[*pc++] | |
/* Dispatch first instruction. */ | |
DISPATCH_NEXT; | |
op_stop: | |
vm->sp = sp; | |
vm->pc = pc; | |
/* dispatch pointer itself never changes */ | |
return; | |
op_beep: | |
printf("beep!\n"); | |
DISPATCH_NEXT; | |
op_moo: | |
printf("moo!\n"); | |
DISPATCH_NEXT; | |
/* Unreachable */ | |
} | |
inline void initInterp(VM *vm) { interp_send(IM_INIT_DISPATCH, vm); } | |
inline void runInterp(VM *vm) { interp_send(IM_RUN, vm); } | |
inline void toggleInterpMode(VM *vm) { interp_send(IM_TOGGLE, vm); } | |
int main(int argc, char *argv[]) { | |
Instr code[] = { OP_BEEP, OP_BEEP, OP_STOP }; | |
VM vm; | |
vm.pc = &code[0]; | |
vm.sp = NULL; | |
initInterp(&vm); | |
runInterp(&vm); /* Should print: beep, beep */ | |
toggleInterpMode(&vm); /* Should print: moo, moo */ | |
vm.pc = &code[0]; | |
runInterp(&vm); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment