Commit b415dd0d authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Add support for O(1) signature indexing without resorting to

[GNU] ld tricks (instead we rely on cpp tricks and some heuristics
for memory allocation) so we probably should rewrite labcomm compiler
to generate cleaner code for this use-case.
parent ef2ec643
......@@ -34,3 +34,5 @@ lib/c/test/test_labcomm_generated_encoding
lib/java/se/lth/control/labcomm/WriterWrapper.class
lib/c/liblabcomm.so.1
lib/c/test/test_labcomm_pthread_scheduler
lib/c/liblabcomm_plain_c.so.1
lib/c/test/test_signature_plain_c
......@@ -201,8 +201,14 @@ aspect C_CodeGen {
}
public void Program.C_emitC(C_env env) {
C_emitSignature(env);
env.print("#if ! defined(LABCOMM_GEN_CODE) && ");
env.println("! defined(LABCOMM_GEN_SIGNATURE)");
env.println("#define LABCOMM_GEN_CODE");
env.println("#define LABCOMM_GEN_SIGNATURE");
env.println("#endif");
env.println("#if defined(LABCOMM_GEN_CODE)");
for (int i = 0; i < getNumDecl(); i++) {
getDecl(i).C_emitSignatureBitsAndForward(env);
getDecl(i).C_emitDecoder(env);
getDecl(i).C_emitDecoderRegisterHandler(env);
getDecl(i).C_emitDecoderIoctl(env);
......@@ -211,6 +217,12 @@ aspect C_CodeGen {
getDecl(i).C_emitEncoderIoctl(env);
getDecl(i).C_emitSizeof(env);
}
env.println("#endif");
env.println("#if defined(LABCOMM_GEN_SIGNATURE)");
for (int i = 0; i < getNumDecl(); i++) {
getDecl(i).C_emitSignature(env);
}
env.println("#endif");
}
}
......@@ -441,7 +453,7 @@ aspect C_Decoder {
public void SampleDecl.C_emitDecoder(C_env env) {
env = env.nestStruct("v");
env.println("static void decode_" + getName() + "(");
env.println("static void decode_" + env.prefix + getName() + "(");
env.indent();
env.println("struct labcomm_reader *r,");
env.println("void (*handle)(");
......@@ -640,7 +652,7 @@ aspect C_Decoder {
env.indent();
env.println("d,");
env.println("&labcomm_signature_" + env.prefix + getName() + ",");
env.println("(labcomm_decoder_function)decode_" + getName() + ",");
env.println("(labcomm_decoder_function)decode_" + env.prefix + getName() + ",");
env.println("(labcomm_handler_function)handler,");
env.println("context");
env.unindent();
......@@ -701,7 +713,7 @@ aspect C_Encoder {
public void SampleDecl.C_emitEncoder(C_env env) {
env = env.nestStruct("(*v)");
env.println("static int encode_" + getName() + "(");
env.println("static int encode_" + env.prefix + getName() + "(");
env.indent();
env.println("struct labcomm_writer *w,");
env.println(env.prefix + getName() + " *v");
......@@ -725,7 +737,7 @@ aspect C_Encoder {
env.indent();
env.println("return labcomm_internal_encode(e, &labcomm_signature_" +
env.prefix + getName() +
", (labcomm_encoder_function)encode_" + getName() +
", (labcomm_encoder_function)encode_" + env.prefix + getName() +
", v);");
env.unindent();
env.println("}");
......@@ -820,7 +832,7 @@ aspect C_Encoder {
env.indent();
env.println("e,");
env.println("&labcomm_signature_" + env.prefix + getName() + ",");
env.println("(labcomm_encoder_function)encode_" + getName());
env.println("(labcomm_encoder_function)encode_" + env.prefix + getName());
env.unindent();
env.println(");");
env.unindent();
......@@ -868,25 +880,18 @@ aspect C_EncoderIoctl {
aspect C_Signature {
public void ASTNode.C_emitSignature(C_env env) {
public void ASTNode.C_emitSignatureBitsAndForward(C_env env) {
throw new Error(this.getClass().getName() +
".C_emitSignature(C_env env)" +
".C_emitSignaturBitsAndForwarde(C_env env)" +
" not declared");
}
public void Program.C_emitSignature(C_env env) {
for (int i = 0; i < getNumDecl(); i++) {
getDecl(i).C_emitSignature(env);
}
public void Decl.C_emitSignatureBitsAndForward(C_env env) {
}
public void Decl.C_emitSignature(C_env env) {
}
public void SampleDecl.C_emitSignature(C_env env) {
public void SampleDecl.C_emitSignatureBitsAndForward(C_env env) {
env.println("static unsigned char signature_bytes_" +
getName() + "[] = {");
// C_genFlatSignature(env);
env.prefix + getName() + "[] = {");
SignatureList signature = signature();
for (int i = 0 ; i < signature.size() ; i++) {
String comment = signature.getComment(i);
......@@ -904,97 +909,31 @@ aspect C_Signature {
}
env.println("};");
env.println("LABCOMM_DECLARE_SIGNATURE(labcomm_signature_" +
env.prefix + getName() + ") = {");
env.indent();
env.println("LABCOMM_SAMPLE, \"" + getName() + "\",");
env.println("(int (*)(struct labcomm_signature *, void *))labcomm_sizeof_" +
env.prefix + getName() + ",");
env.println("sizeof(signature_bytes_" + getName() + "),");
env.println("signature_bytes_"+ getName());
env.unindent();
env.println(" };");
env.prefix + getName() + ");");
}
public void ASTNode.C_genFlatSignature(C_env env) {
public void ASTNode.C_emitSignature(C_env env) {
throw new Error(this.getClass().getName() +
".C_genFlatSignature(C_env env)" +
".C_emitSignature(C_env env)" +
" not declared");
}
public void TypeDecl.C_genFlatSignature(C_env env) {
getType().C_genFlatSignature(env);
}
public void SampleDecl.C_genFlatSignature(C_env env) {
getType().C_genFlatSignature(env);
}
public void PrimType.C_genFlatSignature(C_env env) {
C_genFlatSignature(env, getToken());
env.println("// " + getName());
}
public void UserType.C_genFlatSignature(C_env env) {
lookupType(getName()).C_genFlatSignature(env);
}
public void ArrayType.C_genFlatSignature(C_env env) {
C_genFlatSignature(env, LABCOMM_ARRAY);
env.println("// LABCOMM_ARRAY");
C_genFlatSignature(env, getNumExp());
env.println("// # of dimensions");
for (int i = 0 ; i < getNumExp() ; i++) {
getExp(i).C_genFlatSignature(env);
env.println("");
}
getType().C_genFlatSignature(env);
}
public void StructType.C_genFlatSignature(C_env env) {
C_genFlatSignature(env, LABCOMM_STRUCT);
env.println("// LABCOMM_STRUCT");
C_genFlatSignature(env, getNumField());
env.println("// # of fields");
for (int i = 0 ; i < getNumField() ; i++) {
getField(i).C_genFlatSignature(env);
}
}
public void Field.C_genFlatSignature(C_env env) {
C_genFlatSignature(env, getName());
env.println("");
getType().C_genFlatSignature(env);
}
public void IntegerLiteral.C_genFlatSignature(C_env env) {
C_genFlatSignature(env, Integer.parseInt(getValue()));
env.print("// " + getValue());
}
public void VariableSize.C_genFlatSignature(C_env env) {
C_genFlatSignature(env, 0);
env.print("// _");
public void Decl.C_emitSignature(C_env env) {
}
public void ASTNode.C_genFlatSignature(C_env env, int value) {
env.print(" ");
for (int i = 24 ; i >= 0 ; i -= 8) {
env.print("0x");
String hex = Integer.toHexString((value >> i) & 0xff);
if (hex.length() == 1) { env.print("0"); }
env.print(hex);
env.print(", ");
}
public void SampleDecl.C_emitSignature(C_env env) {
env.println("LABCOMM_DECLARE_SIGNATURE(labcomm_signature_" +
env.prefix + getName() + ") = {");
env.indent();
env.println("LABCOMM_SAMPLE, \"" + getName() + "\",");
env.println("(int (*)(struct labcomm_signature *, void *))labcomm_sizeof_" +
env.prefix + getName() + ",");
env.println("sizeof(signature_bytes_" + env.prefix + getName() + "),");
env.println("signature_bytes_" + env.prefix + getName());
env.unindent();
env.println(" };");
}
public void ASTNode.C_genFlatSignature(C_env env, String value) {
C_genFlatSignature(env, value.length());
env.println("");
env.print(" ");
for (int i = 0 ; i < value.length() ; i++) {
env.print("'" + value.charAt(i) +"', ");
}
}
}
......
......@@ -5,17 +5,20 @@ CC=gcc
CFLAGS=-g -Wall -Werror -O3 -I. -Itest
LDFLAGS=-L.
#LDLIBS_TEST=-Tlabcomm.linkscript -lcunit -llabcomm
LDLIBS_TEST=-lcunit -llabcomm -Tlabcomm.linkscript -lrt
OBJS=labcomm_memory.o \
labcomm_default_error_handler.o \
labcomm_default_memory.o \
labcomm_default_scheduler.o \
labcomm_time.o labcomm_scheduler.o \
labcomm_encoder.o labcomm_decoder.o \
labcomm.o \
labcomm_dynamic_buffer_writer.o labcomm_fd_reader.o labcomm_fd_writer.o \
labcomm_pthread_scheduler.o \
LDLIBS_TEST=-llabcomm -Tlabcomm.linkscript -lrt
LDLIBS_TEST_PLAIN_C=-llabcomm_plain_c -lrt
OBJS_PLAIN_C=labcomm_memory.o \
labcomm_default_error_handler.o \
labcomm_default_memory.o \
labcomm_default_scheduler.o \
labcomm_time.o labcomm_scheduler.o \
labcomm_encoder.o labcomm_decoder.o \
labcomm.o \
labcomm_dynamic_buffer_writer.o \
labcomm_fd_reader.o labcomm_fd_writer.o \
labcomm_pthread_scheduler.o
OBJS=$(OBJS_PLAIN_C) \
labcomm_signature_gnu_ld_tricks.o
#FIXME: labcomm_mem_reader.o labcomm_mem_writer.o
......@@ -23,7 +26,8 @@ LABCOMM_JAR=../../compiler/labComm.jar
LABCOMM=java -jar $(LABCOMM_JAR)
TESTS=test_labcomm_basic_type_encoding test_labcomm_generated_encoding \
test_labcomm_pthread_scheduler
test_labcomm_pthread_scheduler \
test_signature_plain_c
#
#FIXME: test_labcomm test_labcomm_errors
TEST_DIR=test
......@@ -47,14 +51,21 @@ endif
.PHONY: all run-test clean distclean
all: liblabcomm.a liblabcomm.so.1
all: liblabcomm.a liblabcomm_plain_c.a \
liblabcomm.so.1 liblabcomm_plain_c.so.1
liblabcomm.a: $(OBJS)
ar -r liblabcomm.a $^
ar -r $@ $^
liblabcomm_plain_c.a: $(OBJS_PLAIN_C)
ar -r $@ $^
liblabcomm.so.1: $(OBJS:%.o=%.pic.o)
gcc -shared -Wl,-soname,$@ -o $@ $^ -lc -lrt
liblabcomm_plain_c.so.1: $(OBJS_PLAIN_C:%.o=%.pic.o)
gcc -shared -Wl,-soname,$@ -o $@ $^ -lc -lrt
labcomm.o : labcomm.c labcomm.h labcomm_private.h
labcomm_fd_reader_writer.o : labcomm_fd_reader_writer.c labcomm_fd_reader_writer.h labcomm.h labcomm_private.h
......@@ -81,6 +92,19 @@ $(TEST_DIR)/%.o: $(TEST_DIR)/%.c
$(TEST_DIR)/%: $(TEST_DIR)/%.o liblabcomm.a
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(LDLIBS_TEST)
$(TEST_DIR)/test_signature_plain_c_index.o: \
labcomm_signature_plain_c.c \
$(TEST_DIR)/gen/generated_encoding.c \
$(TEST_DIR)/gen/another_encoding.h \
$(TEST_DIR)/gen/another_encoding.c
$(CC) $(CFLAGS) -o $@ -c $< \
-DALL_LABCOMM_FILES=\"test/test_signature_plain_c.h\"
$(TEST_DIR)/test_signature_plain_c: \
$(TEST_DIR)/test_signature_plain_c.o \
$(TEST_DIR)/test_signature_plain_c_index.o
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_TEST_PLAIN_C)
$(TEST_DIR)/gen:
mkdir -p $@
......@@ -118,6 +142,8 @@ clean:
distclean: clean
$(RM) liblabcomm.so.1
$(RM) liblabcomm.a
$(RM) liblabcomm_plain_c.a
$(RM) liblabcomm_plain_c.so.1
# Extra dependencies
$(TEST_DIR)/test_labcomm_basic_type_encoding.o: labcomm_private.h
......@@ -126,6 +152,8 @@ $(TEST_DIR)/test_labcomm_generated_encoding.o: labcomm_private.h
$(TEST_DIR)/test_labcomm_generated_encoding.o: $(TEST_DIR)/gen/generated_encoding.h
$(TEST_DIR)/test_labcomm_generated_encoding : $(TEST_DIR)/gen/generated_encoding.o
$(TEST_DIR)/test_labcomm: $(TEST_GEN_DIR)/test_sample.o
$(TEST_DIR)/test_signature_plain_c.o: $(TEST_DIR)/gen/another_encoding.h
$(TEST_DIR)/test_signature_plain_c.o: $(TEST_DIR)/gen/generated_encoding.h
labcomm_fd_reader.o: labcomm_private.h
labcomm_fd_writer.o: labcomm_private.h
labcomm_dynamic_buffer_writer.o: labcomm_private.h
......@@ -64,8 +64,10 @@
/*
*
*/
#ifndef LABCOMM_DECLARE_SIGNATURE
#define LABCOMM_DECLARE_SIGNATURE(name) \
struct labcomm_signature __attribute__((section("labcomm"),aligned(1))) name
#endif
/*
* Semi private dynamic memory declarations
......
/*
labcomm_signature_gnu_ld_tricks.h -- signature handling.
labcomm_signature_gnu_ld_tricks.c -- signature handling.
Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
......
/*
labcomm_signature_plain_c.c -- signature handling.
Copyright 2013 Anders Blomdell <anders.blomdell@control.lth.se>
This file is part of LabComm.
LabComm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LabComm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define LABCOMM_DECLARE_SIGNATURE(name) \
struct labcomm_signature __attribute__((aligned(1))) name
#include <errno.h>
#include "labcomm.h"
#include "labcomm_signature.h"
#include "labcomm_private.h"
/* NB: We need to mimic forward declarations done in generated code */
LABCOMM_DECLARE_SIGNATURE(labcomm_sentinel_1);
#define LABCOMM_GEN_CODE
#include ALL_LABCOMM_FILES
#undef LABCOMM_GEN_CODE
LABCOMM_DECLARE_SIGNATURE(labcomm_sentinel_2);
/* NB: We need to force our sentinels out of bss segment, hence -1 */
LABCOMM_DECLARE_SIGNATURE(labcomm_sentinel_1) = { -1, NULL, NULL, 0, NULL};
#define LABCOMM_GEN_SIGNATURE
#include ALL_LABCOMM_FILES
#undef LABCOMM_GEN_SIGNATURE
LABCOMM_DECLARE_SIGNATURE(labcomm_sentinel_2) = { -1, NULL, NULL, 0, NULL};
int labcomm_signature_local_index(struct labcomm_signature *s)
{
int result = -ENOENT;
struct labcomm_signature *labcomm_first_signature;
struct labcomm_signature *labcomm_last_signature;
if (&labcomm_sentinel_1 < &labcomm_sentinel_2) {
labcomm_first_signature = &labcomm_sentinel_1;
labcomm_last_signature = &labcomm_sentinel_2;
} else {
labcomm_first_signature = &labcomm_sentinel_2;
labcomm_last_signature = &labcomm_sentinel_1;
}
if (labcomm_first_signature <= s && s < labcomm_last_signature) {
result = (int)(s - labcomm_first_signature) + LABCOMM_USER - 1;
}
return result;
}
sample void V;
sample byte B;
#include <stdlib.h>
#include <stdio.h>
#include "test/gen/another_encoding.h"
#include "test/gen/generated_encoding.h"
extern int labcomm_signature_local_index(struct labcomm_signature *s);
static void info(char *name, char *full_name,
struct labcomm_signature *signature) {
printf("%s %s %p -> %d\n", name, full_name, signature,
labcomm_signature_local_index(signature));
if (labcomm_signature_local_index(signature) < 0x40) {
exit(1);
}
};
int main(int argc, char *argv[])
{
#define FUNC(name, full_name) \
extern struct labcomm_signature labcomm_signature_##full_name; \
info( #name, #full_name, &labcomm_signature_##full_name)
LABCOMM_FORALL_SAMPLES_generated_encoding(FUNC, ;);
LABCOMM_FORALL_SAMPLES_another_encoding(FUNC, ;);
return 0;
}
#include "gen/generated_encoding.c"
#include "gen/another_encoding.c"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment