diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index 5c4f604aa5853122bbf3d7bc854efbebbe02b2de..2eecee257a926f63c3aad206f86c76c295fb8df4 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -524,6 +524,11 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         list.setElement((int) i, v);
     }
 
+    @Override
+    public void SET_ATTRIB(Object target, Object attributes) {
+        throw implementedAsNode();
+    }
+
     @Override
     public Object STRING_ELT(Object x, long i) {
         RAbstractStringVector vector = guaranteeInstanceOf(RRuntime.asAbstractVector(x), RAbstractStringVector.class);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java
index a6d0515c5166861b7f7047f7142942b638e96445..4cf867b273cbff92497b40304d4b10cc97edc13d 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AttributesAccessNodes.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.ffi.impl.nodes;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -33,10 +34,12 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodesFactory.ATTRIBNodeGen;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodesFactory.CopyMostAttribNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodesFactory.SetAttribNodeGen;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodesFactory.TAGNodeGen;
 import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.GetAttributesNode;
+import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -45,14 +48,18 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
+import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
+import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 
@@ -104,7 +111,7 @@ public final class AttributesAccessNodes {
             } else {
                 CompilerDirectives.transferToInterpreter();
                 String type = obj == null ? "null" : obj.getClass().getSimpleName();
-                throw RError.error(RError.NO_CALLER, Message.GENERIC, "object of type '" + type + "' cannot be attributed");
+                throw RError.error(NO_CALLER, Message.GENERIC, "object of type '" + type + "' cannot be attributed");
             }
         }
 
@@ -186,4 +193,50 @@ public final class AttributesAccessNodes {
             return CopyMostAttribNodeGen.create();
         }
     }
+
+    public abstract static class SetAttribNode extends FFIUpCallNode.Arg2 {
+
+        public static SetAttribNode create() {
+            return SetAttribNodeGen.create();
+        }
+
+        @Specialization
+        protected Object doLanguage(RSharingAttributeStorage target, RLanguage attributes,
+                        @Cached("create()") SetAttributeNode setAttribNode) {
+            return doIt(target, getPairList(attributes), setAttribNode);
+        }
+
+        @Specialization
+        protected Object doIt(RSharingAttributeStorage target, RPairList attributes,
+                        @Cached("create()") SetAttributeNode setAttribNode) {
+            clearAttrs(target);
+            for (RPairList attr : attributes) {
+                Object tag = attr.getTag();
+                if (!(tag instanceof RSymbol)) {
+                    CompilerDirectives.transferToInterpreter();
+                    // GNUR seems to set the attr name to NULL and fails when printing
+                    // To be compatible we don't fail, but at least print warning...
+                    RError.warning(NO_CALLER, Message.GENERIC, String.format("SET_ATTRIB: tag in the attributes pairlist must be a symbol. %s given.", Utils.getTypeName(tag)));
+                    continue;
+                }
+                setAttribNode.execute(target, ((RSymbol) tag).getName(), attr.car());
+            }
+            return RNull.instance;
+        }
+
+        @Fallback
+        protected Object doOthers(Object target, Object attrs) {
+            throw unsupportedTypes("SET_ATTRIB", target, attrs);
+        }
+
+        @TruffleBoundary
+        private static void clearAttrs(RSharingAttributeStorage target) {
+            target.initAttributes(RAttributesLayout.createRAttributes());
+        }
+
+        @TruffleBoundary
+        private RPairList getPairList(RLanguage attributes) {
+            return attributes.getPairList();
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index 0e2b98f28185a2fb91be7bf31b10b7d9aab836c0..7f6d381c227f23e66a43ba6f34bbc6d75e2efb42 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -29,6 +29,7 @@ import com.oracle.truffle.r.ffi.impl.nodes.AsRealNode;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.ATTRIB;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.CopyMostAttrib;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.GetAttrib;
+import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.SetAttribNode;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.TAG;
 import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.CoerceVectorNode;
 import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.VectorToPairListNode;
@@ -242,6 +243,9 @@ public interface StdUpCallsRFFI {
 
     void SET_VECTOR_ELT(Object x, long i, Object v);
 
+    @RFFIUpCallNode(SetAttribNode.class)
+    void SET_ATTRIB(Object target, Object attributes);
+
     @RFFICpointer
     Object RAW(Object x);
 
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
index 3454b09213b81f39223bdb35d5ce54c573c7e210..52b7c3a493fac25d30e1c71676518cce426c53a2 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
@@ -250,39 +250,40 @@
 #define SETCADR_x 244
 #define SETCAR_x 245
 #define SETCDR_x 246
-#define SET_BODY_x 247
-#define SET_CLOENV_x 248
-#define SET_FORMALS_x 249
-#define SET_NAMED_FASTR_x 250
-#define SET_RDEBUG_x 251
-#define SET_RSTEP_x 252
-#define SET_S4_OBJECT_x 253
-#define SET_STRING_ELT_x 254
-#define SET_SYMVALUE_x 255
-#define SET_TAG_x 256
-#define SET_TYPEOF_FASTR_x 257
-#define SET_VECTOR_ELT_x 258
-#define STRING_ELT_x 259
-#define SYMVALUE_x 260
-#define TAG_x 261
-#define TYPEOF_x 262
-#define UNSET_S4_OBJECT_x 263
-#define VECTOR_ELT_x 264
-#define forceSymbols_x 265
-#define getCCallable_x 266
-#define getConnectionClassString_x 267
-#define getEmbeddingDLLInfo_x 268
-#define getOpenModeString_x 269
-#define getSummaryDescription_x 270
-#define isSeekable_x 271
-#define octsize_x 272
-#define registerCCallable_x 273
-#define registerRoutines_x 274
-#define restoreHandlerStacks_x 275
-#define setDotSymbolValues_x 276
-#define unif_rand_x 277
-#define useDynamicSymbols_x 278
+#define SET_ATTRIB_x 247
+#define SET_BODY_x 248
+#define SET_CLOENV_x 249
+#define SET_FORMALS_x 250
+#define SET_NAMED_FASTR_x 251
+#define SET_RDEBUG_x 252
+#define SET_RSTEP_x 253
+#define SET_S4_OBJECT_x 254
+#define SET_STRING_ELT_x 255
+#define SET_SYMVALUE_x 256
+#define SET_TAG_x 257
+#define SET_TYPEOF_FASTR_x 258
+#define SET_VECTOR_ELT_x 259
+#define STRING_ELT_x 260
+#define SYMVALUE_x 261
+#define TAG_x 262
+#define TYPEOF_x 263
+#define UNSET_S4_OBJECT_x 264
+#define VECTOR_ELT_x 265
+#define forceSymbols_x 266
+#define getCCallable_x 267
+#define getConnectionClassString_x 268
+#define getEmbeddingDLLInfo_x 269
+#define getOpenModeString_x 270
+#define getSummaryDescription_x 271
+#define isSeekable_x 272
+#define octsize_x 273
+#define registerCCallable_x 274
+#define registerRoutines_x 275
+#define restoreHandlerStacks_x 276
+#define setDotSymbolValues_x 277
+#define unif_rand_x 278
+#define useDynamicSymbols_x 279
 
-#define UPCALLS_TABLE_SIZE 279
+#define UPCALLS_TABLE_SIZE 280
 
 #endif // RFFI_UPCALLSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
index 70f1a481e0de407c10a7b6e7ac313b55a8569fee..86b8f49235bb5cd42cf05ecb4ec70069d288223d 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -1241,7 +1241,7 @@ void SET_NAMED(SEXP x, int v) {
 
 void SET_ATTRIB(SEXP x, SEXP v) {
     TRACE0();
-    unimplemented("SET_ATTRIB");
+    ((call_SET_ATTRIB) callbacks[SET_ATTRIB_x])(x, v);
 }
 
 void DUPLICATE_ATTRIB(SEXP to, SEXP from) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java
index 6245346502eefc5ea5f4f06ac514c3bfb18b58f1..dfc779e6fd3a5b31e8e97dd7b44b4354356f93e8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributesLayout.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,13 +74,6 @@ public final class RAttributesLayout {
         return EMPTY_ATTRS_LAYOUT.factory.newInstance();
     }
 
-    public static DynamicObject createRAttributes(String[] names, Object[] values) {
-        assert names != null && values != null && names.length == values.length;
-
-        AttrsLayout attrsLayout = new AttrsLayout(names);
-        return attrsLayout.factory.newInstance(values);
-    }
-
     public static DynamicObject createClass(Object cls) {
         return CLASS_ATTRS_LAYOUT.factory.newInstance(cls);
     }
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
index 6c3f566281bfffa0e9f971d7f9806b62f278d8d3..208c28dece6771be98aa7f1070825070689cf4e3 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
@@ -141,3 +141,8 @@ rffi.RfRandomFunctions()
 
 rffi.RfRMultinom()
 rffi.RfFunctions()
+
+setAttrTarget <- c(1,2,3)
+attr(setAttrTarget, 'myattr2') <- 'some value';
+api.SET_ATTRIB(setAttrTarget, as.pairlist(list(myattr=42)))
+setAttrTarget
\ No newline at end of file